1package ice 2 3import ( 4 "encoding/binary" 5 6 "github.com/pion/stun" 7) 8 9// tiebreaker is common helper for ICE-{CONTROLLED,CONTROLLING} 10// and represents the so-called tiebreaker number. 11type tiebreaker uint64 12 13const tiebreakerSize = 8 // 64 bit 14 15// AddToAs adds tiebreaker value to m as t attribute. 16func (a tiebreaker) AddToAs(m *stun.Message, t stun.AttrType) error { 17 v := make([]byte, tiebreakerSize) 18 binary.BigEndian.PutUint64(v, uint64(a)) 19 m.Add(t, v) 20 return nil 21} 22 23// GetFromAs decodes tiebreaker value in message getting it as for t type. 24func (a *tiebreaker) GetFromAs(m *stun.Message, t stun.AttrType) error { 25 v, err := m.Get(t) 26 if err != nil { 27 return err 28 } 29 if err = stun.CheckSize(t, len(v), tiebreakerSize); err != nil { 30 return err 31 } 32 *a = tiebreaker(binary.BigEndian.Uint64(v)) 33 return nil 34} 35 36// AttrControlled represents ICE-CONTROLLED attribute. 37type AttrControlled uint64 38 39// AddTo adds ICE-CONTROLLED to message. 40func (c AttrControlled) AddTo(m *stun.Message) error { 41 return tiebreaker(c).AddToAs(m, stun.AttrICEControlled) 42} 43 44// GetFrom decodes ICE-CONTROLLED from message. 45func (c *AttrControlled) GetFrom(m *stun.Message) error { 46 return (*tiebreaker)(c).GetFromAs(m, stun.AttrICEControlled) 47} 48 49// AttrControlling represents ICE-CONTROLLING attribute. 50type AttrControlling uint64 51 52// AddTo adds ICE-CONTROLLING to message. 53func (c AttrControlling) AddTo(m *stun.Message) error { 54 return tiebreaker(c).AddToAs(m, stun.AttrICEControlling) 55} 56 57// GetFrom decodes ICE-CONTROLLING from message. 58func (c *AttrControlling) GetFrom(m *stun.Message) error { 59 return (*tiebreaker)(c).GetFromAs(m, stun.AttrICEControlling) 60} 61 62// AttrControl is helper that wraps ICE-{CONTROLLED,CONTROLLING}. 63type AttrControl struct { 64 Role Role 65 Tiebreaker uint64 66} 67 68// AddTo adds ICE-CONTROLLED or ICE-CONTROLLING attribute depending on Role. 69func (c AttrControl) AddTo(m *stun.Message) error { 70 if c.Role == Controlling { 71 return tiebreaker(c.Tiebreaker).AddToAs(m, stun.AttrICEControlling) 72 } 73 return tiebreaker(c.Tiebreaker).AddToAs(m, stun.AttrICEControlled) 74} 75 76// GetFrom decodes Role and Tiebreaker value from message. 77func (c *AttrControl) GetFrom(m *stun.Message) error { 78 if m.Contains(stun.AttrICEControlling) { 79 c.Role = Controlling 80 return (*tiebreaker)(&c.Tiebreaker).GetFromAs(m, stun.AttrICEControlling) 81 } 82 if m.Contains(stun.AttrICEControlled) { 83 c.Role = Controlled 84 return (*tiebreaker)(&c.Tiebreaker).GetFromAs(m, stun.AttrICEControlled) 85 } 86 return stun.ErrAttributeNotFound 87} 88