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