chunk_abort.go 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package sctp // nolint:dupl
  2. import (
  3. "errors"
  4. "fmt"
  5. )
  6. /*
  7. Abort represents an SCTP Chunk of type ABORT
  8. The ABORT chunk is sent to the peer of an association to close the
  9. association. The ABORT chunk may contain Cause Parameters to inform
  10. the receiver about the reason of the abort. DATA chunks MUST NOT be
  11. bundled with ABORT. Control chunks (except for INIT, INIT ACK, and
  12. SHUTDOWN COMPLETE) MAY be bundled with an ABORT, but they MUST be
  13. placed before the ABORT in the SCTP packet or they will be ignored by
  14. the receiver.
  15. 0 1 2 3
  16. 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
  17. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  18. | Type = 6 |Reserved |T| Length |
  19. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  20. | |
  21. | zero or more Error Causes |
  22. | |
  23. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  24. */
  25. type chunkAbort struct {
  26. chunkHeader
  27. errorCauses []errorCause
  28. }
  29. var (
  30. errChunkTypeNotAbort = errors.New("ChunkType is not of type ABORT")
  31. errBuildAbortChunkFailed = errors.New("failed build Abort Chunk")
  32. )
  33. func (a *chunkAbort) unmarshal(raw []byte) error {
  34. if err := a.chunkHeader.unmarshal(raw); err != nil {
  35. return err
  36. }
  37. if a.typ != ctAbort {
  38. return fmt.Errorf("%w: actually is %s", errChunkTypeNotAbort, a.typ.String())
  39. }
  40. offset := chunkHeaderSize
  41. for {
  42. if len(raw)-offset < 4 {
  43. break
  44. }
  45. e, err := buildErrorCause(raw[offset:])
  46. if err != nil {
  47. return fmt.Errorf("%w: %v", errBuildAbortChunkFailed, err)
  48. }
  49. offset += int(e.length())
  50. a.errorCauses = append(a.errorCauses, e)
  51. }
  52. return nil
  53. }
  54. func (a *chunkAbort) marshal() ([]byte, error) {
  55. a.chunkHeader.typ = ctAbort
  56. a.flags = 0x00
  57. a.raw = []byte{}
  58. for _, ec := range a.errorCauses {
  59. raw, err := ec.marshal()
  60. if err != nil {
  61. return nil, err
  62. }
  63. a.raw = append(a.raw, raw...)
  64. }
  65. return a.chunkHeader.marshal()
  66. }
  67. func (a *chunkAbort) check() (abort bool, err error) {
  68. return false, nil
  69. }
  70. // String makes chunkAbort printable
  71. func (a *chunkAbort) String() string {
  72. res := a.chunkHeader.String()
  73. for _, cause := range a.errorCauses {
  74. res += fmt.Sprintf("\n - %s", cause)
  75. }
  76. return res
  77. }