chunk_heartbeat_ack.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. package sctp
  2. import (
  3. "errors"
  4. "fmt"
  5. )
  6. /*
  7. chunkHeartbeatAck represents an SCTP Chunk of type HEARTBEAT ACK
  8. An endpoint should send this chunk to its peer endpoint as a response
  9. to a HEARTBEAT chunk (see Section 8.3). A HEARTBEAT ACK is always
  10. sent to the source IP address of the IP datagram containing the
  11. HEARTBEAT chunk to which this ack is responding.
  12. The parameter field contains a variable-length opaque data structure.
  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 = 5 | Chunk Flags | Heartbeat Ack 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 chunkHeartbeatAck struct {
  29. chunkHeader
  30. params []param
  31. }
  32. var (
  33. errUnimplemented = errors.New("unimplemented")
  34. errHeartbeatAckParams = errors.New("heartbeat Ack must have one param")
  35. errHeartbeatAckNotHeartbeatInfo = errors.New("heartbeat Ack must have one param, and it should be a HeartbeatInfo")
  36. errHeartbeatAckMarshalParam = errors.New("unable to marshal parameter for Heartbeat Ack")
  37. )
  38. func (h *chunkHeartbeatAck) unmarshal(raw []byte) error {
  39. return errUnimplemented
  40. }
  41. func (h *chunkHeartbeatAck) marshal() ([]byte, error) {
  42. if len(h.params) != 1 {
  43. return nil, errHeartbeatAckParams
  44. }
  45. switch h.params[0].(type) {
  46. case *paramHeartbeatInfo:
  47. // ParamHeartbeatInfo is valid
  48. default:
  49. return nil, errHeartbeatAckNotHeartbeatInfo
  50. }
  51. out := make([]byte, 0)
  52. for idx, p := range h.params {
  53. pp, err := p.marshal()
  54. if err != nil {
  55. return nil, fmt.Errorf("%w: %v", errHeartbeatAckMarshalParam, err)
  56. }
  57. out = append(out, pp...)
  58. // Chunks (including Type, Length, and Value fields) are padded out
  59. // by the sender with all zero bytes to be a multiple of 4 bytes
  60. // long. This padding MUST NOT be more than 3 bytes in total. The
  61. // Chunk Length value does not include terminating padding of the
  62. // chunk. *However, it does include padding of any variable-length
  63. // parameter except the last parameter in the chunk.* The receiver
  64. // MUST ignore the padding.
  65. if idx != len(h.params)-1 {
  66. out = padByte(out, getPadding(len(pp)))
  67. }
  68. }
  69. h.chunkHeader.typ = ctHeartbeatAck
  70. h.chunkHeader.raw = out
  71. return h.chunkHeader.marshal()
  72. }
  73. func (h *chunkHeartbeatAck) check() (abort bool, err error) {
  74. return false, nil
  75. }