1 // 2 // 3 // Copyright 2018 gRPC authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // 17 // 18 19 #ifndef GRPC_SRC_CPP_EXT_FILTERS_CENSUS_RPC_ENCODING_H 20 #define GRPC_SRC_CPP_EXT_FILTERS_CENSUS_RPC_ENCODING_H 21 22 #include <grpc/support/port_platform.h> 23 #include <stdint.h> 24 #include <string.h> 25 26 #include "absl/base/internal/endian.h" 27 #include "absl/strings/string_view.h" 28 29 namespace grpc { 30 namespace internal { 31 32 // TODO(unknown): This may not be needed. Check to see if opencensus requires 33 // a trailing server response. 34 // RpcServerStatsEncoding encapsulates the logic for encoding and decoding of 35 // rpc server stats messages. Rpc server stats consists of a uint64_t time 36 // value (server latency in nanoseconds). 37 class RpcServerStatsEncoding { 38 public: 39 // Size of encoded RPC server stats. 40 static constexpr size_t kRpcServerStatsSize = 10; 41 // Error value. 42 static constexpr size_t kEncodeDecodeFailure = 0; 43 44 // Deserializes rpc server stats from the incoming 'buf' into *time. Returns 45 // number of bytes decoded. If the buffer is of insufficient size (it must be 46 // at least kRpcServerStatsSize bytes) or the encoding version or field ID are 47 // unrecognized, *time will be set to 0 and it will return 48 // kEncodeDecodeFailure. Inlined for performance reasons. Decode(absl::string_view buf,uint64_t * time)49 static size_t Decode(absl::string_view buf, uint64_t* time) { 50 if (buf.size() < kRpcServerStatsSize) { 51 *time = 0; 52 return kEncodeDecodeFailure; 53 } 54 55 uint8_t version = buf[kVersionIdOffset]; 56 uint32_t fieldID = buf[kServerElapsedTimeOffset]; 57 if (version != kVersionId || fieldID != kServerElapsedTimeField) { 58 *time = 0; 59 return kEncodeDecodeFailure; 60 } 61 *time = absl::little_endian::Load64( 62 &buf[kServerElapsedTimeOffset + kFieldIdSize]); 63 return kRpcServerStatsSize; 64 } 65 66 // Serializes rpc server stats into the provided buffer. It returns the 67 // number of bytes written to the buffer. If the buffer is smaller than 68 // kRpcServerStatsSize bytes it will return kEncodeDecodeFailure. Inlined for 69 // performance reasons. Encode(uint64_t time,char * buf,size_t buf_size)70 static size_t Encode(uint64_t time, char* buf, size_t buf_size) { 71 if (buf_size < kRpcServerStatsSize) { 72 return kEncodeDecodeFailure; 73 } 74 75 buf[kVersionIdOffset] = kVersionId; 76 buf[kServerElapsedTimeOffset] = kServerElapsedTimeField; 77 absl::little_endian::Store64(&buf[kServerElapsedTimeOffset + kFieldIdSize], 78 time); 79 return kRpcServerStatsSize; 80 } 81 82 private: 83 // Size of Version ID. 84 static constexpr size_t kVersionIdSize = 1; 85 // Size of Field ID. 86 static constexpr size_t kFieldIdSize = 1; 87 88 // Offset and value for currently supported version ID. 89 static constexpr size_t kVersionIdOffset = 0; 90 static constexpr size_t kVersionId = 0; 91 92 enum FieldIdValue { 93 kServerElapsedTimeField = 0, 94 }; 95 96 enum FieldSize { 97 kServerElapsedTimeSize = 8, 98 }; 99 100 enum FieldIdOffset { 101 kServerElapsedTimeOffset = kVersionIdSize, 102 }; 103 104 RpcServerStatsEncoding() = delete; 105 RpcServerStatsEncoding(const RpcServerStatsEncoding&) = delete; 106 RpcServerStatsEncoding(RpcServerStatsEncoding&&) = delete; 107 RpcServerStatsEncoding operator=(const RpcServerStatsEncoding&) = delete; 108 RpcServerStatsEncoding operator=(RpcServerStatsEncoding&&) = delete; 109 }; 110 111 } // namespace internal 112 } // namespace grpc 113 114 #endif // GRPC_SRC_CPP_EXT_FILTERS_CENSUS_RPC_ENCODING_H 115