• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 //
3 // Copyright 2016 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 #include "src/core/lib/iomgr/error.h"
19 
20 #include <grpc/status.h>
21 #include <grpc/support/alloc.h>
22 #include <grpc/support/port_platform.h>
23 #include <grpc/support/string_util.h>
24 #include <inttypes.h>
25 #include <string.h>
26 
27 #include "absl/log/check.h"
28 #include "absl/log/log.h"
29 #include "absl/strings/str_cat.h"
30 #include "absl/strings/str_format.h"
31 #include "src/core/util/crash.h"
32 
33 #ifdef GPR_WINDOWS
34 #include <grpc/support/log_windows.h>
35 #endif
36 
37 #include "src/core/lib/debug/trace.h"
38 #include "src/core/lib/slice/slice_internal.h"
39 #include "src/core/util/strerror.h"
40 #include "src/core/util/useful.h"
41 
grpc_status_create(absl::StatusCode code,absl::string_view msg,const grpc_core::DebugLocation & location,size_t children_count,absl::Status * children)42 absl::Status grpc_status_create(absl::StatusCode code, absl::string_view msg,
43                                 const grpc_core::DebugLocation& location,
44                                 size_t children_count, absl::Status* children) {
45   absl::Status s = StatusCreate(code, msg, location, {});
46   for (size_t i = 0; i < children_count; ++i) {
47     if (!children[i].ok()) {
48       grpc_core::StatusAddChild(&s, children[i]);
49     }
50   }
51   return s;
52 }
53 
grpc_os_error(const grpc_core::DebugLocation & location,int err,const char * call_name)54 absl::Status grpc_os_error(const grpc_core::DebugLocation& location, int err,
55                            const char* call_name) {
56   return StatusCreate(
57       absl::StatusCode::kUnknown,
58       absl::StrCat(call_name, ": ", grpc_core::StrError(err), " (", err, ")"),
59       location, {});
60 }
61 
62 #ifdef GPR_WINDOWS
WSAErrorToShortDescription(int err)63 std::string WSAErrorToShortDescription(int err) {
64   switch (err) {
65     case WSAEACCES:
66       return "Permission denied";
67     case WSAEFAULT:
68       return "Bad address";
69     case WSAEMFILE:
70       return "Too many open files";
71     case WSAEMSGSIZE:
72       return "Message too long";
73     case WSAENETDOWN:
74       return "Network is down";
75     case WSAENETUNREACH:
76       return "Network is unreachable";
77     case WSAENETRESET:
78       return "Network dropped connection on reset";
79     case WSAECONNABORTED:
80       return "Connection aborted";
81     case WSAECONNRESET:
82       return "Connection reset";
83     case WSAETIMEDOUT:
84       return "Connection timed out";
85     case WSAECONNREFUSED:
86       return "Connection refused";
87     case WSAEHOSTUNREACH:
88       return "No route to host";
89     default:
90       return "WSA Error";
91   };
92 }
93 // TODO(veblush): lift out of iomgr for use in the WindowsEventEngine
grpc_wsa_error(const grpc_core::DebugLocation & location,int err,absl::string_view call_name)94 absl::Status grpc_wsa_error(const grpc_core::DebugLocation& location, int err,
95                             absl::string_view call_name) {
96   char* utf8_message = gpr_format_message(err);
97   absl::Status status = StatusCreate(
98       absl::StatusCode::kUnavailable,
99       absl::StrCat(call_name, ": ", WSAErrorToShortDescription(err), " (",
100                    utf8_message, " -- ", err, ")"),
101       location, {});
102   StatusSetInt(&status, grpc_core::StatusIntProperty::kRpcStatus,
103                GRPC_STATUS_UNAVAILABLE);
104   gpr_free(utf8_message);
105   return status;
106 }
107 #endif
108 
grpc_error_set_int(grpc_error_handle src,grpc_core::StatusIntProperty which,intptr_t value)109 grpc_error_handle grpc_error_set_int(grpc_error_handle src,
110                                      grpc_core::StatusIntProperty which,
111                                      intptr_t value) {
112   if (src.ok()) {
113     src = absl::UnknownError("");
114     StatusSetInt(&src, grpc_core::StatusIntProperty::kRpcStatus,
115                  GRPC_STATUS_OK);
116   }
117   grpc_core::StatusSetInt(&src, which, value);
118   return src;
119 }
120 
grpc_error_get_int(grpc_error_handle error,grpc_core::StatusIntProperty which,intptr_t * p)121 bool grpc_error_get_int(grpc_error_handle error,
122                         grpc_core::StatusIntProperty which, intptr_t* p) {
123   absl::optional<intptr_t> value = grpc_core::StatusGetInt(error, which);
124   if (value.has_value()) {
125     *p = *value;
126     return true;
127   } else {
128     // TODO(veblush): Remove this once absl::Status migration is done
129     if (which == grpc_core::StatusIntProperty::kRpcStatus) {
130       switch (error.code()) {
131         case absl::StatusCode::kOk:
132           *p = GRPC_STATUS_OK;
133           return true;
134         case absl::StatusCode::kResourceExhausted:
135           *p = GRPC_STATUS_RESOURCE_EXHAUSTED;
136           return true;
137         case absl::StatusCode::kCancelled:
138           *p = GRPC_STATUS_CANCELLED;
139           return true;
140         default:
141           break;
142       }
143     }
144     return false;
145   }
146 }
147 
grpc_error_set_str(grpc_error_handle src,grpc_core::StatusStrProperty which,absl::string_view str)148 grpc_error_handle grpc_error_set_str(grpc_error_handle src,
149                                      grpc_core::StatusStrProperty which,
150                                      absl::string_view str) {
151   if (src.ok()) {
152     src = absl::UnknownError("");
153     StatusSetInt(&src, grpc_core::StatusIntProperty::kRpcStatus,
154                  GRPC_STATUS_OK);
155   }
156   if (which == grpc_core::StatusStrProperty::kDescription) {
157     // To change the message of absl::Status, a new instance should be created
158     // with a code and payload because it doesn't have a setter for it.
159     absl::Status s = absl::Status(src.code(), str);
160     src.ForEachPayload(
161         [&](absl::string_view type_url, const absl::Cord& payload) {
162           s.SetPayload(type_url, payload);
163         });
164     return s;
165   } else {
166     grpc_core::StatusSetStr(&src, which, str);
167   }
168   return src;
169 }
170 
grpc_error_get_str(grpc_error_handle error,grpc_core::StatusStrProperty which,std::string * s)171 bool grpc_error_get_str(grpc_error_handle error,
172                         grpc_core::StatusStrProperty which, std::string* s) {
173   if (which == grpc_core::StatusStrProperty::kDescription) {
174     // absl::Status uses the message field for
175     // grpc_core::StatusStrProperty::kDescription instead of using payload.
176     absl::string_view msg = error.message();
177     if (msg.empty()) {
178       return false;
179     } else {
180       *s = std::string(msg);
181       return true;
182     }
183   } else {
184     absl::optional<std::string> value = grpc_core::StatusGetStr(error, which);
185     if (value.has_value()) {
186       *s = std::move(*value);
187       return true;
188     } else {
189       // TODO(veblush): Remove this once absl::Status migration is done
190       if (which == grpc_core::StatusStrProperty::kGrpcMessage) {
191         switch (error.code()) {
192           case absl::StatusCode::kOk:
193             *s = "";
194             return true;
195           case absl::StatusCode::kCancelled:
196             *s = "CANCELLED";
197             return true;
198           default:
199             break;
200         }
201       }
202       return false;
203     }
204   }
205 }
206 
grpc_error_add_child(grpc_error_handle src,grpc_error_handle child)207 grpc_error_handle grpc_error_add_child(grpc_error_handle src,
208                                        grpc_error_handle child) {
209   if (src.ok()) {
210     return child;
211   } else {
212     if (!child.ok()) {
213       grpc_core::StatusAddChild(&src, child);
214     }
215     return src;
216   }
217 }
218 
grpc_log_error(const char * what,grpc_error_handle error,const char * file,int line)219 bool grpc_log_error(const char* what, grpc_error_handle error, const char* file,
220                     int line) {
221   DCHECK(!error.ok());
222   LOG(ERROR).AtLocation(file, line)
223       << what << ": " << grpc_core::StatusToString(error);
224   return false;
225 }
226