summaryrefslogtreecommitdiff
path: root/vendor/github.com/pion/turn/v2/internal/proto
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/pion/turn/v2/internal/proto')
-rw-r--r--vendor/github.com/pion/turn/v2/internal/proto/addr.go65
-rw-r--r--vendor/github.com/pion/turn/v2/internal/proto/chandata.go140
-rw-r--r--vendor/github.com/pion/turn/v2/internal/proto/chann.go67
-rw-r--r--vendor/github.com/pion/turn/v2/internal/proto/data.go30
-rw-r--r--vendor/github.com/pion/turn/v2/internal/proto/dontfrag.go18
-rw-r--r--vendor/github.com/pion/turn/v2/internal/proto/evenport.go55
-rw-r--r--vendor/github.com/pion/turn/v2/internal/proto/fuzz.go111
-rw-r--r--vendor/github.com/pion/turn/v2/internal/proto/lifetime.go52
-rw-r--r--vendor/github.com/pion/turn/v2/internal/proto/peeraddr.go42
-rw-r--r--vendor/github.com/pion/turn/v2/internal/proto/proto.go30
-rw-r--r--vendor/github.com/pion/turn/v2/internal/proto/relayedaddr.go40
-rw-r--r--vendor/github.com/pion/turn/v2/internal/proto/reqfamily.go61
-rw-r--r--vendor/github.com/pion/turn/v2/internal/proto/reqtrans.go65
-rw-r--r--vendor/github.com/pion/turn/v2/internal/proto/rsrvtoken.go39
14 files changed, 815 insertions, 0 deletions
diff --git a/vendor/github.com/pion/turn/v2/internal/proto/addr.go b/vendor/github.com/pion/turn/v2/internal/proto/addr.go
new file mode 100644
index 0000000..b1d654d
--- /dev/null
+++ b/vendor/github.com/pion/turn/v2/internal/proto/addr.go
@@ -0,0 +1,65 @@
+package proto
+
+import (
+ "fmt"
+ "net"
+)
+
+// Addr is ip:port.
+type Addr struct {
+ IP net.IP
+ Port int
+}
+
+// Network implements net.Addr.
+func (Addr) Network() string { return "turn" }
+
+// FromUDPAddr sets addr to UDPAddr.
+func (a *Addr) FromUDPAddr(n *net.UDPAddr) {
+ a.IP = n.IP
+ a.Port = n.Port
+}
+
+// Equal returns true if b == a.
+func (a Addr) Equal(b Addr) bool {
+ if a.Port != b.Port {
+ return false
+ }
+ return a.IP.Equal(b.IP)
+}
+
+// EqualIP returns true if a and b have equal IP addresses.
+func (a Addr) EqualIP(b Addr) bool {
+ return a.IP.Equal(b.IP)
+}
+
+func (a Addr) String() string {
+ return fmt.Sprintf("%s:%d", a.IP, a.Port)
+}
+
+// FiveTuple represents 5-TUPLE value.
+type FiveTuple struct {
+ Client Addr
+ Server Addr
+ Proto Protocol
+}
+
+func (t FiveTuple) String() string {
+ return fmt.Sprintf("%s->%s (%s)",
+ t.Client, t.Server, t.Proto,
+ )
+}
+
+// Equal returns true if b == t.
+func (t FiveTuple) Equal(b FiveTuple) bool {
+ if t.Proto != b.Proto {
+ return false
+ }
+ if !t.Client.Equal(b.Client) {
+ return false
+ }
+ if !t.Server.Equal(b.Server) {
+ return false
+ }
+ return true
+}
diff --git a/vendor/github.com/pion/turn/v2/internal/proto/chandata.go b/vendor/github.com/pion/turn/v2/internal/proto/chandata.go
new file mode 100644
index 0000000..fb1295b
--- /dev/null
+++ b/vendor/github.com/pion/turn/v2/internal/proto/chandata.go
@@ -0,0 +1,140 @@
+package proto
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "io"
+)
+
+// ChannelData represents The ChannelData Message.
+//
+// See RFC 5766 Section 11.4
+type ChannelData struct {
+ Data []byte // can be subslice of Raw
+ Length int // ignored while encoding, len(Data) is used
+ Number ChannelNumber
+ Raw []byte
+}
+
+// Equal returns true if b == c.
+func (c *ChannelData) Equal(b *ChannelData) bool {
+ if c == nil && b == nil {
+ return true
+ }
+ if c == nil || b == nil {
+ return false
+ }
+ if c.Number != b.Number {
+ return false
+ }
+ if len(c.Data) != len(b.Data) {
+ return false
+ }
+ return bytes.Equal(c.Data, b.Data)
+}
+
+// grow ensures that internal buffer will fit v more bytes and
+// increases it capacity if necessary.
+//
+// Similar to stun.Message.grow method.
+func (c *ChannelData) grow(v int) {
+ n := len(c.Raw) + v
+ for cap(c.Raw) < n {
+ c.Raw = append(c.Raw, 0)
+ }
+ c.Raw = c.Raw[:n]
+}
+
+// Reset resets Length, Data and Raw length.
+func (c *ChannelData) Reset() {
+ c.Raw = c.Raw[:0]
+ c.Length = 0
+ c.Data = c.Data[:0]
+}
+
+// Encode encodes ChannelData Message to Raw.
+func (c *ChannelData) Encode() {
+ c.Raw = c.Raw[:0]
+ c.WriteHeader()
+ c.Raw = append(c.Raw, c.Data...)
+ padded := nearestPaddedValueLength(len(c.Raw))
+ if bytesToAdd := padded - len(c.Raw); bytesToAdd > 0 {
+ for i := 0; i < bytesToAdd; i++ {
+ c.Raw = append(c.Raw, 0)
+ }
+ }
+}
+
+const padding = 4
+
+func nearestPaddedValueLength(l int) int {
+ n := padding * (l / padding)
+ if n < l {
+ n += padding
+ }
+ return n
+}
+
+// WriteHeader writes channel number and length.
+func (c *ChannelData) WriteHeader() {
+ if len(c.Raw) < channelDataHeaderSize {
+ // Making WriteHeader call valid even when c.Raw
+ // is nil or len(c.Raw) is less than needed for header.
+ c.grow(channelDataHeaderSize)
+ }
+ // Early bounds check to guarantee safety of writes below.
+ _ = c.Raw[:channelDataHeaderSize]
+ binary.BigEndian.PutUint16(c.Raw[:channelDataNumberSize], uint16(c.Number))
+ binary.BigEndian.PutUint16(c.Raw[channelDataNumberSize:channelDataHeaderSize],
+ uint16(len(c.Data)),
+ )
+}
+
+// ErrBadChannelDataLength means that channel data length is not equal
+// to actual data length.
+var ErrBadChannelDataLength = errors.New("channelData length != len(Data)")
+
+// Decode decodes The ChannelData Message from Raw.
+func (c *ChannelData) Decode() error {
+ buf := c.Raw
+ if len(buf) < channelDataHeaderSize {
+ return io.ErrUnexpectedEOF
+ }
+ num := binary.BigEndian.Uint16(buf[:channelDataNumberSize])
+ c.Number = ChannelNumber(num)
+ l := binary.BigEndian.Uint16(buf[channelDataNumberSize:channelDataHeaderSize])
+ c.Data = buf[channelDataHeaderSize:]
+ c.Length = int(l)
+ if !c.Number.Valid() {
+ return ErrInvalidChannelNumber
+ }
+ if int(l) < len(c.Data) {
+ c.Data = c.Data[:int(l)]
+ }
+ if int(l) > len(buf[channelDataHeaderSize:]) {
+ return ErrBadChannelDataLength
+ }
+ return nil
+}
+
+const (
+ channelDataLengthSize = 2
+ channelDataNumberSize = channelDataLengthSize
+ channelDataHeaderSize = channelDataLengthSize + channelDataNumberSize
+)
+
+// IsChannelData returns true if buf looks like the ChannelData Message.
+func IsChannelData(buf []byte) bool {
+ if len(buf) < channelDataHeaderSize {
+ return false
+ }
+
+ if int(binary.BigEndian.Uint16(buf[channelDataNumberSize:channelDataHeaderSize])) > len(buf[channelDataHeaderSize:]) {
+ return false
+ }
+
+ // Quick check for channel number.
+ num := binary.BigEndian.Uint16(buf[0:channelNumberSize])
+ return isChannelNumberValid(num)
+}
diff --git a/vendor/github.com/pion/turn/v2/internal/proto/chann.go b/vendor/github.com/pion/turn/v2/internal/proto/chann.go
new file mode 100644
index 0000000..d64ef73
--- /dev/null
+++ b/vendor/github.com/pion/turn/v2/internal/proto/chann.go
@@ -0,0 +1,67 @@
+package proto
+
+import (
+ "encoding/binary"
+ "errors"
+ "strconv"
+
+ "github.com/pion/stun"
+)
+
+// ChannelNumber represents CHANNEL-NUMBER attribute.
+//
+// The CHANNEL-NUMBER attribute contains the number of the channel.
+//
+// RFC 5766 Section 14.1
+type ChannelNumber uint16 // encoded as uint16
+
+func (n ChannelNumber) String() string { return strconv.Itoa(int(n)) }
+
+// 16 bits of uint + 16 bits of RFFU = 0.
+const channelNumberSize = 4
+
+// AddTo adds CHANNEL-NUMBER to message.
+func (n ChannelNumber) AddTo(m *stun.Message) error {
+ v := make([]byte, channelNumberSize)
+ binary.BigEndian.PutUint16(v[:2], uint16(n))
+ // v[2:4] are zeroes (RFFU = 0)
+ m.Add(stun.AttrChannelNumber, v)
+ return nil
+}
+
+// GetFrom decodes CHANNEL-NUMBER from message.
+func (n *ChannelNumber) GetFrom(m *stun.Message) error {
+ v, err := m.Get(stun.AttrChannelNumber)
+ if err != nil {
+ return err
+ }
+ if err = stun.CheckSize(stun.AttrChannelNumber, len(v), channelNumberSize); err != nil {
+ return err
+ }
+ _ = v[channelNumberSize-1] // asserting length
+ *n = ChannelNumber(binary.BigEndian.Uint16(v[:2]))
+ // v[2:4] is RFFU and equals to 0.
+ return nil
+}
+
+// See https://tools.ietf.org/html/rfc5766#section-11:
+//
+// 0x4000 through 0x7FFF: These values are the allowed channel
+// numbers (16,383 possible values).
+const (
+ MinChannelNumber = 0x4000
+ MaxChannelNumber = 0x7FFF
+)
+
+// ErrInvalidChannelNumber means that channel number is not valid as by RFC 5766 Section 11.
+var ErrInvalidChannelNumber = errors.New("channel number not in [0x4000, 0x7FFF]")
+
+// isChannelNumberValid returns true if c in [0x4000, 0x7FFF].
+func isChannelNumberValid(c uint16) bool {
+ return c >= MinChannelNumber && c <= MaxChannelNumber
+}
+
+// Valid returns true if channel number has correct value that complies RFC 5766 Section 11 range.
+func (n ChannelNumber) Valid() bool {
+ return isChannelNumberValid(uint16(n))
+}
diff --git a/vendor/github.com/pion/turn/v2/internal/proto/data.go b/vendor/github.com/pion/turn/v2/internal/proto/data.go
new file mode 100644
index 0000000..64243e0
--- /dev/null
+++ b/vendor/github.com/pion/turn/v2/internal/proto/data.go
@@ -0,0 +1,30 @@
+package proto
+
+import "github.com/pion/stun"
+
+// Data represents DATA attribute.
+//
+// The DATA attribute is present in all Send and Data indications. The
+// value portion of this attribute is variable length and consists of
+// the application data (that is, the data that would immediately follow
+// the UDP header if the data was been sent directly between the client
+// and the peer).
+//
+// RFC 5766 Section 14.4
+type Data []byte
+
+// AddTo adds DATA to message.
+func (d Data) AddTo(m *stun.Message) error {
+ m.Add(stun.AttrData, d)
+ return nil
+}
+
+// GetFrom decodes DATA from message.
+func (d *Data) GetFrom(m *stun.Message) error {
+ v, err := m.Get(stun.AttrData)
+ if err != nil {
+ return err
+ }
+ *d = v
+ return nil
+}
diff --git a/vendor/github.com/pion/turn/v2/internal/proto/dontfrag.go b/vendor/github.com/pion/turn/v2/internal/proto/dontfrag.go
new file mode 100644
index 0000000..eb4d8ca
--- /dev/null
+++ b/vendor/github.com/pion/turn/v2/internal/proto/dontfrag.go
@@ -0,0 +1,18 @@
+package proto
+
+import "github.com/pion/stun"
+
+// DontFragmentAttr represents DONT-FRAGMENT attribute.
+type DontFragmentAttr struct{}
+
+// AddTo adds DONT-FRAGMENT attribute to message.
+func (DontFragmentAttr) AddTo(m *stun.Message) error {
+ m.Add(stun.AttrDontFragment, nil)
+ return nil
+}
+
+// IsSet returns true if DONT-FRAGMENT attribute is set.
+func (DontFragmentAttr) IsSet(m *stun.Message) bool {
+ _, err := m.Get(stun.AttrDontFragment)
+ return err == nil
+}
diff --git a/vendor/github.com/pion/turn/v2/internal/proto/evenport.go b/vendor/github.com/pion/turn/v2/internal/proto/evenport.go
new file mode 100644
index 0000000..a5a3882
--- /dev/null
+++ b/vendor/github.com/pion/turn/v2/internal/proto/evenport.go
@@ -0,0 +1,55 @@
+package proto
+
+import "github.com/pion/stun"
+
+// EvenPort represents EVEN-PORT attribute.
+//
+// This attribute allows the client to request that the port in the
+// relayed transport address be even, and (optionally) that the server
+// reserve the next-higher port number.
+//
+// RFC 5766 Section 14.6
+type EvenPort struct {
+ // ReservePort means that the server is requested to reserve
+ // the next-higher port number (on the same IP address)
+ // for a subsequent allocation.
+ ReservePort bool
+}
+
+func (p EvenPort) String() string {
+ if p.ReservePort {
+ return "reserve: true"
+ }
+ return "reserve: false"
+}
+
+const (
+ evenPortSize = 1
+ firstBitSet = (1 << 8) - 1 // 0b100000000
+)
+
+// AddTo adds EVEN-PORT to message.
+func (p EvenPort) AddTo(m *stun.Message) error {
+ v := make([]byte, evenPortSize)
+ if p.ReservePort {
+ // Set first bit to 1.
+ v[0] = firstBitSet
+ }
+ m.Add(stun.AttrEvenPort, v)
+ return nil
+}
+
+// GetFrom decodes EVEN-PORT from message.
+func (p *EvenPort) GetFrom(m *stun.Message) error {
+ v, err := m.Get(stun.AttrEvenPort)
+ if err != nil {
+ return err
+ }
+ if err = stun.CheckSize(stun.AttrEvenPort, len(v), evenPortSize); err != nil {
+ return err
+ }
+ if v[0]&firstBitSet > 0 {
+ p.ReservePort = true
+ }
+ return nil
+}
diff --git a/vendor/github.com/pion/turn/v2/internal/proto/fuzz.go b/vendor/github.com/pion/turn/v2/internal/proto/fuzz.go
new file mode 100644
index 0000000..1a171fb
--- /dev/null
+++ b/vendor/github.com/pion/turn/v2/internal/proto/fuzz.go
@@ -0,0 +1,111 @@
+// +build gofuzz
+
+package proto
+
+import (
+ "fmt"
+
+ "github.com/pion/stun"
+)
+
+type attr interface {
+ stun.Getter
+ stun.Setter
+}
+
+type attrs []struct {
+ g attr
+ t stun.AttrType
+}
+
+func (a attrs) pick(v byte) struct {
+ g attr
+ t stun.AttrType
+} {
+ idx := int(v) % len(a)
+ return a[idx]
+}
+
+func FuzzSetters(data []byte) int {
+ var (
+ m1 = &stun.Message{
+ Raw: make([]byte, 0, 2048),
+ }
+ m2 = &stun.Message{
+ Raw: make([]byte, 0, 2048),
+ }
+ m3 = &stun.Message{
+ Raw: make([]byte, 0, 2048),
+ }
+ )
+ attributes := attrs{
+ {new(RequestedTransport), stun.AttrRequestedTransport},
+ {new(RelayedAddress), stun.AttrXORRelayedAddress},
+ {new(ChannelNumber), stun.AttrChannelNumber},
+ {new(Data), stun.AttrData},
+ {new(EvenPort), stun.AttrEvenPort},
+ {new(Lifetime), stun.AttrLifetime},
+ {new(ReservationToken), stun.AttrReservationToken},
+ }
+ var firstByte = byte(0)
+ if len(data) > 0 {
+ firstByte = data[0]
+ }
+ a := attributes.pick(firstByte)
+ value := data
+ if len(data) > 1 {
+ value = value[1:]
+ }
+ m1.WriteHeader()
+ m1.Add(a.t, value)
+ err := a.g.GetFrom(m1)
+ if err == stun.ErrAttributeNotFound {
+ fmt.Println("unexpected 404") // nolint
+ panic(err) // nolint
+ }
+ if err != nil {
+ return 1
+ }
+ m2.WriteHeader()
+ if err := a.g.AddTo(m2); err != nil {
+ fmt.Println("failed to add attribute to m2") // nolint
+ panic(err) // nolint
+ }
+ m3.WriteHeader()
+ v, err := m2.Get(a.t)
+ if err != nil {
+ panic(err) // nolint
+ }
+ m3.Add(a.t, v)
+
+ if !m2.Equal(m3) {
+ fmt.Println(m2, "not equal", m3) // nolint
+ panic("not equal") // nolint
+ }
+ return 1
+}
+
+var d = &ChannelData{}
+
+func FuzzChannelData(data []byte) int {
+ d.Reset()
+ if b := bin.Uint16(data[0:4]); b > 20000 {
+ bin.PutUint16(data[0:4], MinChannelNumber-1)
+ } else if b > 40000 {
+ bin.PutUint16(data[0:4], MinChannelNumber+(MaxChannelNumber-MinChannelNumber)%b)
+ }
+ d.Raw = append(d.Raw, data...)
+ if d.Decode() != nil {
+ return 0
+ }
+ d2 := &ChannelData{}
+ d.Encode()
+ if !d.Number.Valid() {
+ return 1
+ }
+ d2.Raw = d.Raw
+ if err := d2.Decode(); err != nil {
+ panic(err) //nolint
+ }
+ return 1
+}
diff --git a/vendor/github.com/pion/turn/v2/internal/proto/lifetime.go b/vendor/github.com/pion/turn/v2/internal/proto/lifetime.go
new file mode 100644
index 0000000..b781696
--- /dev/null
+++ b/vendor/github.com/pion/turn/v2/internal/proto/lifetime.go
@@ -0,0 +1,52 @@
+package proto
+
+import (
+ "encoding/binary"
+ "time"
+
+ "github.com/pion/stun"
+)
+
+// DefaultLifetime in RFC 5766 is 10 minutes.
+//
+// RFC 5766 Section 2.2
+const DefaultLifetime = time.Minute * 10
+
+// Lifetime represents LIFETIME attribute.
+//
+// The LIFETIME attribute represents the duration for which the server
+// will maintain an allocation in the absence of a refresh. The value
+// portion of this attribute is 4-bytes long and consists of a 32-bit
+// unsigned integral value representing the number of seconds remaining
+// until expiration.
+//
+// RFC 5766 Section 14.2
+type Lifetime struct {
+ time.Duration
+}
+
+// uint32 seconds
+const lifetimeSize = 4 // 4 bytes, 32 bits
+
+// AddTo adds LIFETIME to message.
+func (l Lifetime) AddTo(m *stun.Message) error {
+ v := make([]byte, lifetimeSize)
+ binary.BigEndian.PutUint32(v, uint32(l.Seconds()))
+ m.Add(stun.AttrLifetime, v)
+ return nil
+}
+
+// GetFrom decodes LIFETIME from message.
+func (l *Lifetime) GetFrom(m *stun.Message) error {
+ v, err := m.Get(stun.AttrLifetime)
+ if err != nil {
+ return err
+ }
+ if err = stun.CheckSize(stun.AttrLifetime, len(v), lifetimeSize); err != nil {
+ return err
+ }
+ _ = v[lifetimeSize-1] // asserting length
+ seconds := binary.BigEndian.Uint32(v)
+ l.Duration = time.Second * time.Duration(seconds)
+ return nil
+}
diff --git a/vendor/github.com/pion/turn/v2/internal/proto/peeraddr.go b/vendor/github.com/pion/turn/v2/internal/proto/peeraddr.go
new file mode 100644
index 0000000..b357b82
--- /dev/null
+++ b/vendor/github.com/pion/turn/v2/internal/proto/peeraddr.go
@@ -0,0 +1,42 @@
+package proto
+
+import (
+ "net"
+
+ "github.com/pion/stun"
+)
+
+// PeerAddress implements XOR-PEER-ADDRESS attribute.
+//
+// The XOR-PEER-ADDRESS specifies the address and port of the peer as
+// seen from the TURN server. (For example, the peer's server-reflexive
+// transport address if the peer is behind a NAT.)
+//
+// RFC 5766 Section 14.3
+type PeerAddress struct {
+ IP net.IP
+ Port int
+}
+
+func (a PeerAddress) String() string {
+ return stun.XORMappedAddress(a).String()
+}
+
+// AddTo adds XOR-PEER-ADDRESS to message.
+func (a PeerAddress) AddTo(m *stun.Message) error {
+ return stun.XORMappedAddress(a).AddToAs(m, stun.AttrXORPeerAddress)
+}
+
+// GetFrom decodes XOR-PEER-ADDRESS from message.
+func (a *PeerAddress) GetFrom(m *stun.Message) error {
+ return (*stun.XORMappedAddress)(a).GetFromAs(m, stun.AttrXORPeerAddress)
+}
+
+// XORPeerAddress implements XOR-PEER-ADDRESS attribute.
+//
+// The XOR-PEER-ADDRESS specifies the address and port of the peer as
+// seen from the TURN server. (For example, the peer's server-reflexive
+// transport address if the peer is behind a NAT.)
+//
+// RFC 5766 Section 14.3
+type XORPeerAddress = PeerAddress
diff --git a/vendor/github.com/pion/turn/v2/internal/proto/proto.go b/vendor/github.com/pion/turn/v2/internal/proto/proto.go
new file mode 100644
index 0000000..4b08c76
--- /dev/null
+++ b/vendor/github.com/pion/turn/v2/internal/proto/proto.go
@@ -0,0 +1,30 @@
+// Package proto implements RFC 5766 Traversal Using Relays around NAT.
+//
+// Merged from gortc/turn v0.80.
+package proto
+
+import (
+ "github.com/pion/stun"
+)
+
+// Default ports for TURN from RFC 5766 Section 4.
+const (
+ // DefaultPort for TURN is same as STUN.
+ DefaultPort = stun.DefaultPort
+ // DefaultTLSPort is for TURN over TLS and is same as STUN.
+ DefaultTLSPort = stun.DefaultTLSPort
+)
+
+// CreatePermissionRequest is shorthand for create permission request type.
+func CreatePermissionRequest() stun.MessageType {
+ return stun.NewType(stun.MethodCreatePermission, stun.ClassRequest)
+}
+
+// AllocateRequest is shorthand for allocation request message type.
+func AllocateRequest() stun.MessageType { return stun.NewType(stun.MethodAllocate, stun.ClassRequest) }
+
+// SendIndication is shorthand for send indication message type.
+func SendIndication() stun.MessageType { return stun.NewType(stun.MethodSend, stun.ClassIndication) }
+
+// RefreshRequest is shorthand for refresh request message type.
+func RefreshRequest() stun.MessageType { return stun.NewType(stun.MethodRefresh, stun.ClassRequest) }
diff --git a/vendor/github.com/pion/turn/v2/internal/proto/relayedaddr.go b/vendor/github.com/pion/turn/v2/internal/proto/relayedaddr.go
new file mode 100644
index 0000000..2169cb7
--- /dev/null
+++ b/vendor/github.com/pion/turn/v2/internal/proto/relayedaddr.go
@@ -0,0 +1,40 @@
+package proto
+
+import (
+ "net"
+
+ "github.com/pion/stun"
+)
+
+// RelayedAddress implements XOR-RELAYED-ADDRESS attribute.
+//
+// It specifies the address and port that the server allocated to the
+// client. It is encoded in the same way as XOR-MAPPED-ADDRESS.
+//
+// RFC 5766 Section 14.5
+type RelayedAddress struct {
+ IP net.IP
+ Port int
+}
+
+func (a RelayedAddress) String() string {
+ return stun.XORMappedAddress(a).String()
+}
+
+// AddTo adds XOR-PEER-ADDRESS to message.
+func (a RelayedAddress) AddTo(m *stun.Message) error {
+ return stun.XORMappedAddress(a).AddToAs(m, stun.AttrXORRelayedAddress)
+}
+
+// GetFrom decodes XOR-PEER-ADDRESS from message.
+func (a *RelayedAddress) GetFrom(m *stun.Message) error {
+ return (*stun.XORMappedAddress)(a).GetFromAs(m, stun.AttrXORRelayedAddress)
+}
+
+// XORRelayedAddress implements XOR-RELAYED-ADDRESS attribute.
+//
+// It specifies the address and port that the server allocated to the
+// client. It is encoded in the same way as XOR-MAPPED-ADDRESS.
+//
+// RFC 5766 Section 14.5
+type XORRelayedAddress = RelayedAddress
diff --git a/vendor/github.com/pion/turn/v2/internal/proto/reqfamily.go b/vendor/github.com/pion/turn/v2/internal/proto/reqfamily.go
new file mode 100644
index 0000000..e83d6bb
--- /dev/null
+++ b/vendor/github.com/pion/turn/v2/internal/proto/reqfamily.go
@@ -0,0 +1,61 @@
+package proto
+
+import (
+ "errors"
+
+ "github.com/pion/stun"
+)
+
+// RequestedAddressFamily represents the REQUESTED-ADDRESS-FAMILY Attribute as
+// defined in RFC 6156 Section 4.1.1.
+type RequestedAddressFamily byte
+
+const requestedFamilySize = 4
+
+var errInvalidRequestedFamilyValue = errors.New("invalid value for requested family attribute")
+
+// GetFrom decodes REQUESTED-ADDRESS-FAMILY from message.
+func (f *RequestedAddressFamily) GetFrom(m *stun.Message) error {
+ v, err := m.Get(stun.AttrRequestedAddressFamily)
+ if err != nil {
+ return err
+ }
+ if err = stun.CheckSize(stun.AttrRequestedAddressFamily, len(v), requestedFamilySize); err != nil {
+ return err
+ }
+ switch v[0] {
+ case byte(RequestedFamilyIPv4), byte(RequestedFamilyIPv6):
+ *f = RequestedAddressFamily(v[0])
+ default:
+ return errInvalidRequestedFamilyValue
+ }
+ return nil
+}
+
+func (f RequestedAddressFamily) String() string {
+ switch f {
+ case RequestedFamilyIPv4:
+ return "IPv4"
+ case RequestedFamilyIPv6:
+ return "IPv6"
+ default:
+ return "unknown"
+ }
+}
+
+// AddTo adds REQUESTED-ADDRESS-FAMILY to message.
+func (f RequestedAddressFamily) AddTo(m *stun.Message) error {
+ v := make([]byte, requestedFamilySize)
+ v[0] = byte(f)
+ // b[1:4] is RFFU = 0.
+ // The RFFU field MUST be set to zero on transmission and MUST be
+ // ignored on reception. It is reserved for future uses.
+ m.Add(stun.AttrRequestedAddressFamily, v)
+ return nil
+}
+
+// Values for RequestedAddressFamily as defined in RFC 6156 Section 4.1.1.
+const (
+ RequestedFamilyIPv4 RequestedAddressFamily = 0x01
+ RequestedFamilyIPv6 RequestedAddressFamily = 0x02
+)
diff --git a/vendor/github.com/pion/turn/v2/internal/proto/reqtrans.go b/vendor/github.com/pion/turn/v2/internal/proto/reqtrans.go
new file mode 100644
index 0000000..a4e4863
--- /dev/null
+++ b/vendor/github.com/pion/turn/v2/internal/proto/reqtrans.go
@@ -0,0 +1,65 @@
+package proto
+
+import (
+ "strconv"
+
+ "github.com/pion/stun"
+)
+
+// Protocol is IANA assigned protocol number.
+type Protocol byte
+
+const (
+ // ProtoUDP is IANA assigned protocol number for UDP.
+ ProtoUDP Protocol = 17
+)
+
+func (p Protocol) String() string {
+ switch p {
+ case ProtoUDP:
+ return "UDP"
+ default:
+ return strconv.Itoa(int(p))
+ }
+}
+
+// RequestedTransport represents REQUESTED-TRANSPORT attribute.
+//
+// This attribute is used by the client to request a specific transport
+// protocol for the allocated transport address. RFC 5766 only allows the use of
+// codepoint 17 (User Datagram Protocol).
+//
+// RFC 5766 Section 14.7
+type RequestedTransport struct {
+ Protocol Protocol
+}
+
+func (t RequestedTransport) String() string {
+ return "protocol: " + t.Protocol.String()
+}
+
+const requestedTransportSize = 4
+
+// AddTo adds REQUESTED-TRANSPORT to message.
+func (t RequestedTransport) AddTo(m *stun.Message) error {
+ v := make([]byte, requestedTransportSize)
+ v[0] = byte(t.Protocol)
+ // b[1:4] is RFFU = 0.
+ // The RFFU field MUST be set to zero on transmission and MUST be
+ // ignored on reception. It is reserved for future uses.
+ m.Add(stun.AttrRequestedTransport, v)
+ return nil
+}
+
+// GetFrom decodes REQUESTED-TRANSPORT from message.
+func (t *RequestedTransport) GetFrom(m *stun.Message) error {
+ v, err := m.Get(stun.AttrRequestedTransport)
+ if err != nil {
+ return err
+ }
+ if err = stun.CheckSize(stun.AttrRequestedTransport, len(v), requestedTransportSize); err != nil {
+ return err
+ }
+ t.Protocol = Protocol(v[0])
+ return nil
+}
diff --git a/vendor/github.com/pion/turn/v2/internal/proto/rsrvtoken.go b/vendor/github.com/pion/turn/v2/internal/proto/rsrvtoken.go
new file mode 100644
index 0000000..6e2ed4d
--- /dev/null
+++ b/vendor/github.com/pion/turn/v2/internal/proto/rsrvtoken.go
@@ -0,0 +1,39 @@
+package proto
+
+import "github.com/pion/stun"
+
+// ReservationToken represents RESERVATION-TOKEN attribute.
+//
+// The RESERVATION-TOKEN attribute contains a token that uniquely
+// identifies a relayed transport address being held in reserve by the
+// server. The server includes this attribute in a success response to
+// tell the client about the token, and the client includes this
+// attribute in a subsequent Allocate request to request the server use
+// that relayed transport address for the allocation.
+//
+// RFC 5766 Section 14.9
+type ReservationToken []byte
+
+const reservationTokenSize = 8 // 8 bytes
+
+// AddTo adds RESERVATION-TOKEN to message.
+func (t ReservationToken) AddTo(m *stun.Message) error {
+ if err := stun.CheckSize(stun.AttrReservationToken, len(t), reservationTokenSize); err != nil {
+ return err
+ }
+ m.Add(stun.AttrReservationToken, t)
+ return nil
+}
+
+// GetFrom decodes RESERVATION-TOKEN from message.
+func (t *ReservationToken) GetFrom(m *stun.Message) error {
+ v, err := m.Get(stun.AttrReservationToken)
+ if err != nil {
+ return err
+ }
+ if err = stun.CheckSize(stun.AttrReservationToken, len(v), reservationTokenSize); err != nil {
+ return err
+ }
+ *t = v
+ return nil
+}