1 // 2 // 3 // Copyright 2015 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 GRPCPP_IMPL_METADATA_MAP_H 20 #define GRPCPP_IMPL_METADATA_MAP_H 21 22 #include <map> 23 24 #include <grpc/grpc.h> 25 #include <grpc/support/log.h> 26 #include <grpcpp/support/slice.h> 27 28 namespace grpc { 29 30 namespace internal { 31 32 const char kBinaryErrorDetailsKey[] = "grpc-status-details-bin"; 33 34 class MetadataMap { 35 public: MetadataMap()36 MetadataMap() { Setup(); } 37 ~MetadataMap()38 ~MetadataMap() { Destroy(); } 39 GetBinaryErrorDetails()40 std::string GetBinaryErrorDetails() { 41 // if filled_, extract from the multimap for O(log(n)) 42 if (filled_) { 43 auto iter = map_.find(kBinaryErrorDetailsKey); 44 if (iter != map_.end()) { 45 return std::string(iter->second.begin(), iter->second.length()); 46 } 47 } 48 // if not yet filled, take the O(n) lookup to avoid allocating the 49 // multimap until it is requested. 50 // TODO(ncteisen): plumb this through core as a first class object, just 51 // like code and message. 52 else { 53 for (size_t i = 0; i < arr_.count; i++) { 54 if (strncmp(reinterpret_cast<const char*>( 55 GRPC_SLICE_START_PTR(arr_.metadata[i].key)), 56 kBinaryErrorDetailsKey, 57 GRPC_SLICE_LENGTH(arr_.metadata[i].key)) == 0) { 58 return std::string(reinterpret_cast<const char*>( 59 GRPC_SLICE_START_PTR(arr_.metadata[i].value)), 60 GRPC_SLICE_LENGTH(arr_.metadata[i].value)); 61 } 62 } 63 } 64 return std::string(); 65 } 66 map()67 std::multimap<grpc::string_ref, grpc::string_ref>* map() { 68 FillMap(); 69 return &map_; 70 } arr()71 grpc_metadata_array* arr() { return &arr_; } 72 Reset()73 void Reset() { 74 filled_ = false; 75 map_.clear(); 76 Destroy(); 77 Setup(); 78 } 79 80 private: 81 bool filled_ = false; 82 grpc_metadata_array arr_; 83 std::multimap<grpc::string_ref, grpc::string_ref> map_; 84 Destroy()85 void Destroy() { grpc_metadata_array_destroy(&arr_); } 86 Setup()87 void Setup() { memset(&arr_, 0, sizeof(arr_)); } 88 FillMap()89 void FillMap() { 90 if (filled_) return; 91 filled_ = true; 92 for (size_t i = 0; i < arr_.count; i++) { 93 // TODO(yangg) handle duplicates? 94 map_.insert(std::pair<grpc::string_ref, grpc::string_ref>( 95 StringRefFromSlice(&arr_.metadata[i].key), 96 StringRefFromSlice(&arr_.metadata[i].value))); 97 } 98 } 99 }; 100 } // namespace internal 101 102 } // namespace grpc 103 104 #endif // GRPCPP_IMPL_METADATA_MAP_H 105