chunk_heartbeat.go 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package sctp
  2. import (
  3. "errors"
  4. "fmt"
  5. )
  6. /*
  7. chunkHeartbeat represents an SCTP Chunk of type HEARTBEAT
  8. An endpoint should send this chunk to its peer endpoint to probe the
  9. reachability of a particular destination transport address defined in
  10. the present association.
  11. The parameter field contains the Heartbeat Information, which is a
  12. variable-length opaque data structure understood only by the sender.
  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 = 4 | Chunk Flags | Heartbeat Length |
  17. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  18. | |
  19. | Heartbeat Information TLV (Variable-Length) |
  20. | |
  21. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  22. Defined as a variable-length parameter using the format described
  23. in Section 3.2.1, i.e.:
  24. Variable Parameters Status Type Value
  25. -------------------------------------------------------------
  26. heartbeat Info Mandatory 1
  27. */
  28. type chunkHeartbeat struct {
  29. chunkHeader
  30. params []param
  31. }
  32. // Heartbeat chunk errors
  33. var (
  34. ErrChunkTypeNotHeartbeat = errors.New("ChunkType is not of type HEARTBEAT")
  35. ErrHeartbeatNotLongEnoughInfo = errors.New("heartbeat is not long enough to contain Heartbeat Info")
  36. ErrParseParamTypeFailed = errors.New("failed to parse param type")
  37. ErrHeartbeatParam = errors.New("heartbeat should only have HEARTBEAT param")
  38. ErrHeartbeatChunkUnmarshal = errors.New("failed unmarshalling param in Heartbeat Chunk")
  39. )
  40. func (h *chunkHeartbeat) unmarshal(raw []byte) error {
  41. if err := h.chunkHeader.unmarshal(raw); err != nil {
  42. return err
  43. } else if h.typ != ctHeartbeat {
  44. return fmt.Errorf("%w: actually is %s", ErrChunkTypeNotHeartbeat, h.typ.String())
  45. }
  46. if len(raw) <= chunkHeaderSize {
  47. return fmt.Errorf("%w: %d", ErrHeartbeatNotLongEnoughInfo, len(raw))
  48. }
  49. pType, err := parseParamType(raw[chunkHeaderSize:])
  50. if err != nil {
  51. return fmt.Errorf("%w: %v", ErrParseParamTypeFailed, err) //nolint:errorlint
  52. }
  53. if pType != heartbeatInfo {
  54. return fmt.Errorf("%w: instead have %s", ErrHeartbeatParam, pType.String())
  55. }
  56. p, err := buildParam(pType, raw[chunkHeaderSize:])
  57. if err != nil {
  58. return fmt.Errorf("%w: %v", ErrHeartbeatChunkUnmarshal, err) //nolint:errorlint
  59. }
  60. h.params = append(h.params, p)
  61. return nil
  62. }
  63. func (h *chunkHeartbeat) Marshal() ([]byte, error) {
  64. return nil, ErrUnimplemented
  65. }
  66. func (h *chunkHeartbeat) check() (abort bool, err error) {
  67. return false, nil
  68. }