chunk_reconfig.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package sctp
  2. import (
  3. "errors"
  4. "fmt"
  5. )
  6. // https://tools.ietf.org/html/rfc6525#section-3.1
  7. // chunkReconfig represents an SCTP Chunk used to reconfigure streams.
  8. //
  9. // 0 1 2 3
  10. // 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
  11. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  12. // | Type = 130 | Chunk Flags | Chunk Length |
  13. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  14. // \ \
  15. // / Re-configuration Parameter /
  16. // \ \
  17. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  18. // \ \
  19. // / Re-configuration Parameter (optional) /
  20. // \ \
  21. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  22. type chunkReconfig struct {
  23. chunkHeader
  24. paramA param
  25. paramB param
  26. }
  27. // Reconfigure chunk errors
  28. var (
  29. ErrChunkParseParamTypeFailed = errors.New("failed to parse param type")
  30. ErrChunkMarshalParamAReconfigFailed = errors.New("unable to marshal parameter A for reconfig")
  31. ErrChunkMarshalParamBReconfigFailed = errors.New("unable to marshal parameter B for reconfig")
  32. )
  33. func (c *chunkReconfig) unmarshal(raw []byte) error {
  34. if err := c.chunkHeader.unmarshal(raw); err != nil {
  35. return err
  36. }
  37. pType, err := parseParamType(c.raw)
  38. if err != nil {
  39. return fmt.Errorf("%w: %v", ErrChunkParseParamTypeFailed, err) //nolint:errorlint
  40. }
  41. a, err := buildParam(pType, c.raw)
  42. if err != nil {
  43. return err
  44. }
  45. c.paramA = a
  46. padding := getPadding(a.length())
  47. offset := a.length() + padding
  48. if len(c.raw) > offset {
  49. pType, err := parseParamType(c.raw[offset:])
  50. if err != nil {
  51. return fmt.Errorf("%w: %v", ErrChunkParseParamTypeFailed, err) //nolint:errorlint
  52. }
  53. b, err := buildParam(pType, c.raw[offset:])
  54. if err != nil {
  55. return err
  56. }
  57. c.paramB = b
  58. }
  59. return nil
  60. }
  61. func (c *chunkReconfig) marshal() ([]byte, error) {
  62. out, err := c.paramA.marshal()
  63. if err != nil {
  64. return nil, fmt.Errorf("%w: %v", ErrChunkMarshalParamAReconfigFailed, err) //nolint:errorlint
  65. }
  66. if c.paramB != nil {
  67. // Pad param A
  68. out = padByte(out, getPadding(len(out)))
  69. outB, err := c.paramB.marshal()
  70. if err != nil {
  71. return nil, fmt.Errorf("%w: %v", ErrChunkMarshalParamBReconfigFailed, err) //nolint:errorlint
  72. }
  73. out = append(out, outB...)
  74. }
  75. c.typ = ctReconfig
  76. c.raw = out
  77. return c.chunkHeader.marshal()
  78. }
  79. func (c *chunkReconfig) check() (abort bool, err error) {
  80. // nolint:godox
  81. // TODO: check allowed combinations:
  82. // https://tools.ietf.org/html/rfc6525#section-3.1
  83. return true, nil
  84. }
  85. // String makes chunkReconfig printable
  86. func (c *chunkReconfig) String() string {
  87. res := fmt.Sprintf("Param A:\n %s", c.paramA)
  88. if c.paramB != nil {
  89. res += fmt.Sprintf("Param B:\n %s", c.paramB)
  90. }
  91. return res
  92. }