aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/grpc/src/core/lib/channel/status_util.cc
blob: 5f5cd2a1d8ebdd43004a73e3240af0ceeea6a49d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//
//
// Copyright 2017 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//

#include <grpc/support/port_platform.h>

#include "src/core/lib/channel/status_util.h"

#include <string.h>

#include <algorithm>
#include <vector>

#include "y_absl/strings/str_cat.h"
#include "y_absl/strings/str_join.h"

#include "src/core/lib/gpr/useful.h"

struct status_string_entry {
  const char* str;
  grpc_status_code status;
};
static const status_string_entry g_status_string_entries[] = {
    {"OK", GRPC_STATUS_OK},
    {"CANCELLED", GRPC_STATUS_CANCELLED},
    {"UNKNOWN", GRPC_STATUS_UNKNOWN},
    {"INVALID_ARGUMENT", GRPC_STATUS_INVALID_ARGUMENT},
    {"DEADLINE_EXCEEDED", GRPC_STATUS_DEADLINE_EXCEEDED},
    {"NOT_FOUND", GRPC_STATUS_NOT_FOUND},
    {"ALREADY_EXISTS", GRPC_STATUS_ALREADY_EXISTS},
    {"PERMISSION_DENIED", GRPC_STATUS_PERMISSION_DENIED},
    {"UNAUTHENTICATED", GRPC_STATUS_UNAUTHENTICATED},
    {"RESOURCE_EXHAUSTED", GRPC_STATUS_RESOURCE_EXHAUSTED},
    {"FAILED_PRECONDITION", GRPC_STATUS_FAILED_PRECONDITION},
    {"ABORTED", GRPC_STATUS_ABORTED},
    {"OUT_OF_RANGE", GRPC_STATUS_OUT_OF_RANGE},
    {"UNIMPLEMENTED", GRPC_STATUS_UNIMPLEMENTED},
    {"INTERNAL", GRPC_STATUS_INTERNAL},
    {"UNAVAILABLE", GRPC_STATUS_UNAVAILABLE},
    {"DATA_LOSS", GRPC_STATUS_DATA_LOSS},
};

bool grpc_status_code_from_string(const char* status_str,
                                  grpc_status_code* status) {
  for (size_t i = 0; i < GPR_ARRAY_SIZE(g_status_string_entries); ++i) {
    if (strcmp(status_str, g_status_string_entries[i].str) == 0) {
      *status = g_status_string_entries[i].status;
      return true;
    }
  }
  return false;
}

const char* grpc_status_code_to_string(grpc_status_code status) {
  switch (status) {
    case GRPC_STATUS_OK:
      return "OK";
    case GRPC_STATUS_CANCELLED:
      return "CANCELLED";
    case GRPC_STATUS_UNKNOWN:
      return "UNKNOWN";
    case GRPC_STATUS_INVALID_ARGUMENT:
      return "INVALID_ARGUMENT";
    case GRPC_STATUS_DEADLINE_EXCEEDED:
      return "DEADLINE_EXCEEDED";
    case GRPC_STATUS_NOT_FOUND:
      return "NOT_FOUND";
    case GRPC_STATUS_ALREADY_EXISTS:
      return "ALREADY_EXISTS";
    case GRPC_STATUS_PERMISSION_DENIED:
      return "PERMISSION_DENIED";
    case GRPC_STATUS_RESOURCE_EXHAUSTED:
      return "RESOURCE_EXHAUSTED";
    case GRPC_STATUS_FAILED_PRECONDITION:
      return "FAILED_PRECONDITION";
    case GRPC_STATUS_ABORTED:
      return "ABORTED";
    case GRPC_STATUS_OUT_OF_RANGE:
      return "OUT_OF_RANGE";
    case GRPC_STATUS_UNIMPLEMENTED:
      return "UNIMPLEMENTED";
    case GRPC_STATUS_INTERNAL:
      return "INTERNAL";
    case GRPC_STATUS_UNAVAILABLE:
      return "UNAVAILABLE";
    case GRPC_STATUS_DATA_LOSS:
      return "DATA_LOSS";
    case GRPC_STATUS_UNAUTHENTICATED:
      return "UNAUTHENTICATED";
    default:
      return "UNKNOWN";
  }
}

bool grpc_status_code_from_int(int status_int, grpc_status_code* status) {
  // The range of status code enum is [0, 16], 0 is OK, 16 is UNAUTHENTICATED.
  if (status_int < GRPC_STATUS_OK || status_int > GRPC_STATUS_UNAUTHENTICATED) {
    *status = GRPC_STATUS_UNKNOWN;
    return false;
  }
  *status = static_cast<grpc_status_code>(status_int);
  return true;
}

namespace grpc_core {

namespace internal {

TString StatusCodeSet::ToString() const {
  std::vector<y_absl::string_view> codes;
  for (size_t i = 0; i < GPR_ARRAY_SIZE(g_status_string_entries); ++i) {
    if (Contains(g_status_string_entries[i].status)) {
      codes.emplace_back(g_status_string_entries[i].str);
    }
  }
  return y_absl::StrCat("{", y_absl::StrJoin(codes, ","), "}");
}

}  // namespace internal

y_absl::Status MaybeRewriteIllegalStatusCode(y_absl::Status status,
                                           y_absl::string_view source) {
  switch (status.code()) {
    // The set of disallowed codes, as per
    // https://github.com/grpc/proposal/blob/master/A54-restrict-control-plane-status-codes.md.
    case y_absl::StatusCode::kInvalidArgument:
    case y_absl::StatusCode::kNotFound:
    case y_absl::StatusCode::kAlreadyExists:
    case y_absl::StatusCode::kFailedPrecondition:
    case y_absl::StatusCode::kAborted:
    case y_absl::StatusCode::kOutOfRange:
    case y_absl::StatusCode::kDataLoss: {
      return y_absl::InternalError(
          y_absl::StrCat("Illegal status code from ", source,
                       "; original status: ", status.ToString()));
    }
    default:
      return status;
  }
}

}  // namespace grpc_core