errorcode.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. package stun
  4. import (
  5. "errors"
  6. "fmt"
  7. "io"
  8. )
  9. // ErrorCodeAttribute represents ERROR-CODE attribute.
  10. //
  11. // RFC 5389 Section 15.6
  12. type ErrorCodeAttribute struct {
  13. Code ErrorCode
  14. Reason []byte
  15. }
  16. func (c ErrorCodeAttribute) String() string {
  17. return fmt.Sprintf("%d: %s", c.Code, c.Reason)
  18. }
  19. // constants for ERROR-CODE encoding.
  20. const (
  21. errorCodeReasonStart = 4
  22. errorCodeClassByte = 2
  23. errorCodeNumberByte = 3
  24. errorCodeReasonMaxB = 763
  25. errorCodeModulo = 100
  26. )
  27. // AddTo adds ERROR-CODE to m.
  28. func (c ErrorCodeAttribute) AddTo(m *Message) error {
  29. value := make([]byte, 0, errorCodeReasonStart+errorCodeReasonMaxB)
  30. if err := CheckOverflow(AttrErrorCode,
  31. len(c.Reason)+errorCodeReasonStart,
  32. errorCodeReasonMaxB+errorCodeReasonStart,
  33. ); err != nil {
  34. return err
  35. }
  36. value = value[:errorCodeReasonStart+len(c.Reason)]
  37. number := byte(c.Code % errorCodeModulo) // error code modulo 100
  38. class := byte(c.Code / errorCodeModulo) // hundred digit
  39. value[errorCodeClassByte] = class
  40. value[errorCodeNumberByte] = number
  41. copy(value[errorCodeReasonStart:], c.Reason)
  42. m.Add(AttrErrorCode, value)
  43. return nil
  44. }
  45. // GetFrom decodes ERROR-CODE from m. Reason is valid until m.Raw is valid.
  46. func (c *ErrorCodeAttribute) GetFrom(m *Message) error {
  47. v, err := m.Get(AttrErrorCode)
  48. if err != nil {
  49. return err
  50. }
  51. if len(v) < errorCodeReasonStart {
  52. return io.ErrUnexpectedEOF
  53. }
  54. var (
  55. class = uint16(v[errorCodeClassByte])
  56. number = uint16(v[errorCodeNumberByte])
  57. code = int(class*errorCodeModulo + number)
  58. )
  59. c.Code = ErrorCode(code)
  60. c.Reason = v[errorCodeReasonStart:]
  61. return nil
  62. }
  63. // ErrorCode is code for ERROR-CODE attribute.
  64. type ErrorCode int
  65. // ErrNoDefaultReason means that default reason for provided error code
  66. // is not defined in RFC.
  67. var ErrNoDefaultReason = errors.New("no default reason for ErrorCode")
  68. // AddTo adds ERROR-CODE with default reason to m. If there
  69. // is no default reason, returns ErrNoDefaultReason.
  70. func (c ErrorCode) AddTo(m *Message) error {
  71. reason := errorReasons[c]
  72. if reason == nil {
  73. return ErrNoDefaultReason
  74. }
  75. a := &ErrorCodeAttribute{
  76. Code: c,
  77. Reason: reason,
  78. }
  79. return a.AddTo(m)
  80. }
  81. // Possible error codes.
  82. const (
  83. CodeTryAlternate ErrorCode = 300
  84. CodeBadRequest ErrorCode = 400
  85. CodeUnauthorized ErrorCode = 401
  86. CodeUnknownAttribute ErrorCode = 420
  87. CodeStaleNonce ErrorCode = 438
  88. CodeRoleConflict ErrorCode = 487
  89. CodeServerError ErrorCode = 500
  90. )
  91. // DEPRECATED constants.
  92. const (
  93. // DEPRECATED, use CodeUnauthorized.
  94. CodeUnauthorised = CodeUnauthorized
  95. )
  96. // Error codes from RFC 5766.
  97. //
  98. // RFC 5766 Section 15
  99. const (
  100. CodeForbidden ErrorCode = 403 // Forbidden
  101. CodeAllocMismatch ErrorCode = 437 // Allocation Mismatch
  102. CodeWrongCredentials ErrorCode = 441 // Wrong Credentials
  103. CodeUnsupportedTransProto ErrorCode = 442 // Unsupported Transport Protocol
  104. CodeAllocQuotaReached ErrorCode = 486 // Allocation Quota Reached
  105. CodeInsufficientCapacity ErrorCode = 508 // Insufficient Capacity
  106. )
  107. // Error codes from RFC 6062.
  108. //
  109. // RFC 6062 Section 6.3
  110. const (
  111. CodeConnAlreadyExists ErrorCode = 446
  112. CodeConnTimeoutOrFailure ErrorCode = 447
  113. )
  114. // Error codes from RFC 6156.
  115. //
  116. // RFC 6156 Section 10.2
  117. const (
  118. CodeAddrFamilyNotSupported ErrorCode = 440 // Address Family not Supported
  119. CodePeerAddrFamilyMismatch ErrorCode = 443 // Peer Address Family Mismatch
  120. )
  121. //nolint:gochecknoglobals
  122. var errorReasons = map[ErrorCode][]byte{
  123. CodeTryAlternate: []byte("Try Alternate"),
  124. CodeBadRequest: []byte("Bad Request"),
  125. CodeUnauthorized: []byte("Unauthorized"),
  126. CodeUnknownAttribute: []byte("Unknown Attribute"),
  127. CodeStaleNonce: []byte("Stale Nonce"),
  128. CodeServerError: []byte("Server Error"),
  129. CodeRoleConflict: []byte("Role Conflict"),
  130. // RFC 5766.
  131. CodeForbidden: []byte("Forbidden"),
  132. CodeAllocMismatch: []byte("Allocation Mismatch"),
  133. CodeWrongCredentials: []byte("Wrong Credentials"),
  134. CodeUnsupportedTransProto: []byte("Unsupported Transport Protocol"),
  135. CodeAllocQuotaReached: []byte("Allocation Quota Reached"),
  136. CodeInsufficientCapacity: []byte("Insufficient Capacity"),
  137. // RFC 6062.
  138. CodeConnAlreadyExists: []byte("Connection Already Exists"),
  139. CodeConnTimeoutOrFailure: []byte("Connection Timeout or Failure"),
  140. // RFC 6156.
  141. CodeAddrFamilyNotSupported: []byte("Address Family not Supported"),
  142. CodePeerAddrFamilyMismatch: []byte("Peer Address Family Mismatch"),
  143. }