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