-
Notifications
You must be signed in to change notification settings - Fork 79
/
chunk_error.go
103 lines (83 loc) · 2.59 KB
/
chunk_error.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
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
package sctp // nolint:dupl
import (
"errors"
"fmt"
)
/*
Operation Error (ERROR) (9)
An endpoint sends this chunk to its peer endpoint to notify it of
certain error conditions. It contains one or more error causes. An
Operation Error is not considered fatal in and of itself, but may be
used with an ERROR chunk to report a fatal condition. It has the
following parameters:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type = 9 | Chunk Flags | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\ \
/ one or more Error Causes /
\ \
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Chunk Flags: 8 bits
Set to 0 on transmit and ignored on receipt.
Length: 16 bits (unsigned integer)
Set to the size of the chunk in bytes, including the chunk header
and all the Error Cause fields present.
*/
type chunkError struct {
chunkHeader
errorCauses []errorCause
}
// Error chunk errors
var (
ErrChunkTypeNotCtError = errors.New("ChunkType is not of type ctError")
ErrBuildErrorChunkFailed = errors.New("failed build Error Chunk")
)
func (a *chunkError) unmarshal(raw []byte) error {
if err := a.chunkHeader.unmarshal(raw); err != nil {
return err
}
if a.typ != ctError {
return fmt.Errorf("%w, actually is %s", ErrChunkTypeNotCtError, a.typ.String())
}
offset := chunkHeaderSize
for {
if len(raw)-offset < 4 {
break
}
e, err := buildErrorCause(raw[offset:])
if err != nil {
return fmt.Errorf("%w: %v", ErrBuildErrorChunkFailed, err) //nolint:errorlint
}
offset += int(e.length())
a.errorCauses = append(a.errorCauses, e)
}
return nil
}
func (a *chunkError) marshal() ([]byte, error) {
a.chunkHeader.typ = ctError
a.flags = 0x00
a.raw = []byte{}
for _, ec := range a.errorCauses {
raw, err := ec.marshal()
if err != nil {
return nil, err
}
a.raw = append(a.raw, raw...)
}
return a.chunkHeader.marshal()
}
func (a *chunkError) check() (abort bool, err error) {
return false, nil
}
// String makes chunkError printable
func (a *chunkError) String() string {
res := a.chunkHeader.String()
for _, cause := range a.errorCauses {
res += fmt.Sprintf("\n - %s", cause)
}
return res
}