chunk_error.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package sctp // nolint:dupl
  2. import (
  3. "errors"
  4. "fmt"
  5. )
  6. /*
  7. Operation Error (ERROR) (9)
  8. An endpoint sends this chunk to its peer endpoint to notify it of
  9. certain error conditions. It contains one or more error causes. An
  10. Operation Error is not considered fatal in and of itself, but may be
  11. used with an ERROR chunk to report a fatal condition. It has the
  12. following parameters:
  13. 0 1 2 3
  14. 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
  15. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  16. | Type = 9 | Chunk Flags | Length |
  17. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  18. \ \
  19. / one or more Error Causes /
  20. \ \
  21. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  22. Chunk Flags: 8 bits
  23. Set to 0 on transmit and ignored on receipt.
  24. Length: 16 bits (unsigned integer)
  25. Set to the size of the chunk in bytes, including the chunk header
  26. and all the Error Cause fields present.
  27. */
  28. type chunkError struct {
  29. chunkHeader
  30. errorCauses []errorCause
  31. }
  32. var (
  33. errChunkTypeNotCtError = errors.New("ChunkType is not of type ctError")
  34. errBuildErrorChunkFailed = errors.New("failed build Error Chunk")
  35. )
  36. func (a *chunkError) unmarshal(raw []byte) error {
  37. if err := a.chunkHeader.unmarshal(raw); err != nil {
  38. return err
  39. }
  40. if a.typ != ctError {
  41. return fmt.Errorf("%w, actually is %s", errChunkTypeNotCtError, a.typ.String())
  42. }
  43. offset := chunkHeaderSize
  44. for {
  45. if len(raw)-offset < 4 {
  46. break
  47. }
  48. e, err := buildErrorCause(raw[offset:])
  49. if err != nil {
  50. return fmt.Errorf("%w: %v", errBuildErrorChunkFailed, err)
  51. }
  52. offset += int(e.length())
  53. a.errorCauses = append(a.errorCauses, e)
  54. }
  55. return nil
  56. }
  57. func (a *chunkError) marshal() ([]byte, error) {
  58. a.chunkHeader.typ = ctError
  59. a.flags = 0x00
  60. a.raw = []byte{}
  61. for _, ec := range a.errorCauses {
  62. raw, err := ec.marshal()
  63. if err != nil {
  64. return nil, err
  65. }
  66. a.raw = append(a.raw, raw...)
  67. }
  68. return a.chunkHeader.marshal()
  69. }
  70. func (a *chunkError) check() (abort bool, err error) {
  71. return false, nil
  72. }
  73. // String makes chunkError printable
  74. func (a *chunkError) String() string {
  75. res := a.chunkHeader.String()
  76. for _, cause := range a.errorCauses {
  77. res += fmt.Sprintf("\n - %s", cause)
  78. }
  79. return res
  80. }