-
Notifications
You must be signed in to change notification settings - Fork 14
/
common.go
300 lines (254 loc) · 8.71 KB
/
common.go
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
package apistatus
import (
"encoding/binary"
"errors"
"github.com/nspcc-dev/neofs-api-go/v2/status"
)
// Error describes common error which is a grouping type for any [apistatus] errors. Any [apistatus] error may be checked
// explicitly via it's type of just check the group via errors.Is(err, [apistatus.Error]).
var Error = errors.New("api error")
var (
// ErrServerInternal is an instance of ServerInternal error status. It's expected to be used for [errors.Is]
// and MUST NOT be changed.
ErrServerInternal ServerInternal
// ErrWrongMagicNumber is an instance of WrongMagicNumber error status. It's expected to be used for [errors.Is]
// and MUST NOT be changed.
ErrWrongMagicNumber WrongMagicNumber
// ErrSignatureVerification is an instance of SignatureVerification error status. It's expected to be used for [errors.Is]
// and MUST NOT be changed.
ErrSignatureVerification SignatureVerification
// ErrNodeUnderMaintenance is an instance of NodeUnderMaintenance error status. It's expected to be used for [errors.Is]
// and MUST NOT be changed.
ErrNodeUnderMaintenance NodeUnderMaintenance
)
// ServerInternal describes failure statuses related to internal server errors.
// Instances provide [StatusV2] and error interfaces.
//
// The status is purely informative, the client should not go into details of the error except for debugging needs.
type ServerInternal struct {
v2 status.Status
}
func (x ServerInternal) Error() string {
return errMessageStatusV2(
globalizeCodeV2(status.Internal, status.GlobalizeCommonFail),
x.v2.Message(),
)
}
// Is implements interface for correct checking current error type with [errors.Is].
func (x ServerInternal) Is(target error) bool {
switch target.(type) {
default:
return errors.Is(Error, target)
case ServerInternal, *ServerInternal:
return true
}
}
// implements local interface defined in [ErrorFromV2] func.
func (x *ServerInternal) fromStatusV2(st *status.Status) {
x.v2 = *st
}
// ErrorToV2 implements [StatusV2] interface method.
// If the value was returned by [ErrorFromV2], returns the source message.
// Otherwise, returns message with
// - code: INTERNAL;
// - string message: empty;
// - details: empty.
func (x ServerInternal) ErrorToV2() *status.Status {
x.v2.SetCode(globalizeCodeV2(status.Internal, status.GlobalizeCommonFail))
return &x.v2
}
// SetMessage sets message describing internal error.
//
// Message should be used for debug purposes only.
func (x *ServerInternal) SetMessage(msg string) {
x.v2.SetMessage(msg)
}
// Message returns message describing internal server error.
//
// Message should be used for debug purposes only. By default, it is empty.
func (x ServerInternal) Message() string {
return x.v2.Message()
}
// WriteInternalServerErr writes err message to ServerInternal instance.
func WriteInternalServerErr(x *ServerInternal, err error) {
x.SetMessage(err.Error())
}
// WrongMagicNumber describes failure status related to incorrect network magic.
// Instances provide [StatusV2] and error interfaces.
type WrongMagicNumber struct {
v2 status.Status
}
func (x WrongMagicNumber) Error() string {
return errMessageStatusV2(
globalizeCodeV2(status.WrongMagicNumber, status.GlobalizeCommonFail),
x.v2.Message(),
)
}
// Is implements interface for correct checking current error type with [errors.Is].
func (x WrongMagicNumber) Is(target error) bool {
switch target.(type) {
default:
return errors.Is(Error, target)
case WrongMagicNumber, *WrongMagicNumber:
return true
}
}
// implements local interface defined in [ErrorFromV2] func.
func (x *WrongMagicNumber) fromStatusV2(st *status.Status) {
x.v2 = *st
}
// ErrorToV2 implements [StatusV2] interface method.
// If the value was returned by [ErrorFromV2], returns the source message.
// Otherwise, returns message with
// - code: WRONG_MAGIC_NUMBER;
// - string message: empty;
// - details: empty.
func (x WrongMagicNumber) ErrorToV2() *status.Status {
x.v2.SetCode(globalizeCodeV2(status.WrongMagicNumber, status.GlobalizeCommonFail))
return &x.v2
}
// WriteCorrectMagic writes correct network magic.
func (x *WrongMagicNumber) WriteCorrectMagic(magic uint64) {
// serialize the number
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, magic)
// create corresponding detail
var d status.Detail
d.SetID(status.DetailIDCorrectMagic)
d.SetValue(buf)
// attach the detail
x.v2.AppendDetails(d)
}
// CorrectMagic returns network magic returned by the server.
// Second value indicates presence status:
// - -1 if number is presented in incorrect format
// - 0 if number is not presented
// - +1 otherwise
func (x WrongMagicNumber) CorrectMagic() (magic uint64, ok int8) {
x.v2.IterateDetails(func(d *status.Detail) bool {
if d.ID() == status.DetailIDCorrectMagic {
if val := d.Value(); len(val) == 8 {
magic = binary.BigEndian.Uint64(val)
ok = 1
} else {
ok = -1
}
}
return ok != 0
})
return
}
// SignatureVerification describes failure status related to signature verification.
// Instances provide [StatusV2] and error interfaces.
type SignatureVerification struct {
v2 status.Status
}
const defaultSignatureVerificationMsg = "signature verification failed"
func (x SignatureVerification) Error() string {
msg := x.v2.Message()
if msg == "" {
msg = defaultSignatureVerificationMsg
}
return errMessageStatusV2(
globalizeCodeV2(status.SignatureVerificationFail, status.GlobalizeCommonFail),
msg,
)
}
// Is implements interface for correct checking current error type with [errors.Is].
func (x SignatureVerification) Is(target error) bool {
switch target.(type) {
default:
return errors.Is(Error, target)
case SignatureVerification, *SignatureVerification:
return true
}
}
// implements local interface defined in [ErrorFromV2] func.
func (x *SignatureVerification) fromStatusV2(st *status.Status) {
x.v2 = *st
}
// ErrorToV2 implements [StatusV2] interface method.
// If the value was returned by [ErrorFromV2], returns the source message.
// Otherwise, returns message with
// - code: SIGNATURE_VERIFICATION_FAIL;
// - string message: written message via [SignatureVerification.SetMessage] or
// "signature verification failed" as a default message;
// - details: empty.
func (x SignatureVerification) ErrorToV2() *status.Status {
x.v2.SetCode(globalizeCodeV2(status.SignatureVerificationFail, status.GlobalizeCommonFail))
if x.v2.Message() == "" {
x.v2.SetMessage(defaultSignatureVerificationMsg)
}
return &x.v2
}
// SetMessage writes signature verification failure message.
// Message should be used for debug purposes only.
//
// See also Message.
func (x *SignatureVerification) SetMessage(v string) {
x.v2.SetMessage(v)
}
// Message returns status message. Zero status returns empty message.
// Message should be used for debug purposes only.
//
// See also SetMessage.
func (x SignatureVerification) Message() string {
return x.v2.Message()
}
// NodeUnderMaintenance describes failure status for nodes being under maintenance.
// Instances provide [StatusV2] and error interfaces.
type NodeUnderMaintenance struct {
v2 status.Status
}
const defaultNodeUnderMaintenanceMsg = "node is under maintenance"
// Error implements the error interface.
func (x NodeUnderMaintenance) Error() string {
msg := x.Message()
if msg == "" {
msg = defaultNodeUnderMaintenanceMsg
}
return errMessageStatusV2(
globalizeCodeV2(status.NodeUnderMaintenance, status.GlobalizeCommonFail),
msg,
)
}
// Is implements interface for correct checking current error type with [errors.Is].
func (x NodeUnderMaintenance) Is(target error) bool {
switch target.(type) {
default:
return errors.Is(Error, target)
case NodeUnderMaintenance, *NodeUnderMaintenance:
return true
}
}
func (x *NodeUnderMaintenance) fromStatusV2(st *status.Status) {
x.v2 = *st
}
// ErrorToV2 implements [StatusV2] interface method.
// If the value was returned by [ErrorFromV2], returns the source message.
// Otherwise, returns message with
// - code: NODE_UNDER_MAINTENANCE;
// - string message: written message via [NodeUnderMaintenance.SetMessage] or
// "node is under maintenance" as a default message;
// - details: empty.
func (x NodeUnderMaintenance) ErrorToV2() *status.Status {
x.v2.SetCode(globalizeCodeV2(status.NodeUnderMaintenance, status.GlobalizeCommonFail))
if x.v2.Message() == "" {
x.v2.SetMessage(defaultNodeUnderMaintenanceMsg)
}
return &x.v2
}
// SetMessage writes signature verification failure message.
// Message should be used for debug purposes only.
//
// See also Message.
func (x *NodeUnderMaintenance) SetMessage(v string) {
x.v2.SetMessage(v)
}
// Message returns status message. Zero status returns empty message.
// Message should be used for debug purposes only.
//
// See also SetMessage.
func (x NodeUnderMaintenance) Message() string {
return x.v2.Message()
}