1 //
2 //
3 // Copyright 2017 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 #include "src/core/lib/channel/status_util.h"
20
21 #include <grpc/support/port_platform.h>
22 #include <string.h>
23
24 #include <vector>
25
26 #include "absl/strings/str_cat.h"
27 #include "absl/strings/str_join.h"
28 #include "src/core/util/useful.h"
29
30 struct status_string_entry {
31 const char* str;
32 grpc_status_code status;
33 };
34 static const status_string_entry g_status_string_entries[] = {
35 {"OK", GRPC_STATUS_OK},
36 {"CANCELLED", GRPC_STATUS_CANCELLED},
37 {"UNKNOWN", GRPC_STATUS_UNKNOWN},
38 {"INVALID_ARGUMENT", GRPC_STATUS_INVALID_ARGUMENT},
39 {"DEADLINE_EXCEEDED", GRPC_STATUS_DEADLINE_EXCEEDED},
40 {"NOT_FOUND", GRPC_STATUS_NOT_FOUND},
41 {"ALREADY_EXISTS", GRPC_STATUS_ALREADY_EXISTS},
42 {"PERMISSION_DENIED", GRPC_STATUS_PERMISSION_DENIED},
43 {"UNAUTHENTICATED", GRPC_STATUS_UNAUTHENTICATED},
44 {"RESOURCE_EXHAUSTED", GRPC_STATUS_RESOURCE_EXHAUSTED},
45 {"FAILED_PRECONDITION", GRPC_STATUS_FAILED_PRECONDITION},
46 {"ABORTED", GRPC_STATUS_ABORTED},
47 {"OUT_OF_RANGE", GRPC_STATUS_OUT_OF_RANGE},
48 {"UNIMPLEMENTED", GRPC_STATUS_UNIMPLEMENTED},
49 {"INTERNAL", GRPC_STATUS_INTERNAL},
50 {"UNAVAILABLE", GRPC_STATUS_UNAVAILABLE},
51 {"DATA_LOSS", GRPC_STATUS_DATA_LOSS},
52 };
53
grpc_status_code_from_string(const char * status_str,grpc_status_code * status)54 bool grpc_status_code_from_string(const char* status_str,
55 grpc_status_code* status) {
56 for (size_t i = 0; i < GPR_ARRAY_SIZE(g_status_string_entries); ++i) {
57 if (strcmp(status_str, g_status_string_entries[i].str) == 0) {
58 *status = g_status_string_entries[i].status;
59 return true;
60 }
61 }
62 return false;
63 }
64
grpc_status_code_to_string(grpc_status_code status)65 const char* grpc_status_code_to_string(grpc_status_code status) {
66 switch (status) {
67 case GRPC_STATUS_OK:
68 return "OK";
69 case GRPC_STATUS_CANCELLED:
70 return "CANCELLED";
71 case GRPC_STATUS_UNKNOWN:
72 return "UNKNOWN";
73 case GRPC_STATUS_INVALID_ARGUMENT:
74 return "INVALID_ARGUMENT";
75 case GRPC_STATUS_DEADLINE_EXCEEDED:
76 return "DEADLINE_EXCEEDED";
77 case GRPC_STATUS_NOT_FOUND:
78 return "NOT_FOUND";
79 case GRPC_STATUS_ALREADY_EXISTS:
80 return "ALREADY_EXISTS";
81 case GRPC_STATUS_PERMISSION_DENIED:
82 return "PERMISSION_DENIED";
83 case GRPC_STATUS_RESOURCE_EXHAUSTED:
84 return "RESOURCE_EXHAUSTED";
85 case GRPC_STATUS_FAILED_PRECONDITION:
86 return "FAILED_PRECONDITION";
87 case GRPC_STATUS_ABORTED:
88 return "ABORTED";
89 case GRPC_STATUS_OUT_OF_RANGE:
90 return "OUT_OF_RANGE";
91 case GRPC_STATUS_UNIMPLEMENTED:
92 return "UNIMPLEMENTED";
93 case GRPC_STATUS_INTERNAL:
94 return "INTERNAL";
95 case GRPC_STATUS_UNAVAILABLE:
96 return "UNAVAILABLE";
97 case GRPC_STATUS_DATA_LOSS:
98 return "DATA_LOSS";
99 case GRPC_STATUS_UNAUTHENTICATED:
100 return "UNAUTHENTICATED";
101 default:
102 return "UNKNOWN";
103 }
104 }
105
grpc_status_code_from_int(int status_int,grpc_status_code * status)106 bool grpc_status_code_from_int(int status_int, grpc_status_code* status) {
107 // The range of status code enum is [0, 16], 0 is OK, 16 is UNAUTHENTICATED.
108 if (status_int < GRPC_STATUS_OK || status_int > GRPC_STATUS_UNAUTHENTICATED) {
109 *status = GRPC_STATUS_UNKNOWN;
110 return false;
111 }
112 *status = static_cast<grpc_status_code>(status_int);
113 return true;
114 }
115
116 namespace grpc_core {
117
118 namespace internal {
119
ToString() const120 std::string StatusCodeSet::ToString() const {
121 std::vector<absl::string_view> codes;
122 for (size_t i = 0; i < GPR_ARRAY_SIZE(g_status_string_entries); ++i) {
123 if (Contains(g_status_string_entries[i].status)) {
124 codes.emplace_back(g_status_string_entries[i].str);
125 }
126 }
127 return absl::StrCat("{", absl::StrJoin(codes, ","), "}");
128 }
129
130 } // namespace internal
131
MaybeRewriteIllegalStatusCode(absl::Status status,absl::string_view source)132 absl::Status MaybeRewriteIllegalStatusCode(absl::Status status,
133 absl::string_view source) {
134 switch (status.code()) {
135 // The set of disallowed codes, as per
136 // https://github.com/grpc/proposal/blob/master/A54-restrict-control-plane-status-codes.md.
137 case absl::StatusCode::kInvalidArgument:
138 case absl::StatusCode::kNotFound:
139 case absl::StatusCode::kAlreadyExists:
140 case absl::StatusCode::kFailedPrecondition:
141 case absl::StatusCode::kAborted:
142 case absl::StatusCode::kOutOfRange:
143 case absl::StatusCode::kDataLoss: {
144 return absl::InternalError(
145 absl::StrCat("Illegal status code from ", source,
146 "; original status: ", status.ToString()));
147 }
148 default:
149 return status;
150 }
151 }
152
153 } // namespace grpc_core
154