123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
- // SPDX-License-Identifier: MIT
- package stun
- import (
- "fmt"
- "io"
- "net"
- "strconv"
- )
- // MappedAddress represents MAPPED-ADDRESS attribute.
- //
- // This attribute is used only by servers for achieving backwards
- // compatibility with RFC 3489 clients.
- //
- // RFC 5389 Section 15.1
- type MappedAddress struct {
- IP net.IP
- Port int
- }
- // AlternateServer represents ALTERNATE-SERVER attribute.
- //
- // RFC 5389 Section 15.11
- type AlternateServer struct {
- IP net.IP
- Port int
- }
- // ResponseOrigin represents RESPONSE-ORIGIN attribute.
- //
- // RFC 5780 Section 7.3
- type ResponseOrigin struct {
- IP net.IP
- Port int
- }
- // OtherAddress represents OTHER-ADDRESS attribute.
- //
- // RFC 5780 Section 7.4
- type OtherAddress struct {
- IP net.IP
- Port int
- }
- // AddTo adds ALTERNATE-SERVER attribute to message.
- func (s *AlternateServer) AddTo(m *Message) error {
- a := (*MappedAddress)(s)
- return a.AddToAs(m, AttrAlternateServer)
- }
- // GetFrom decodes ALTERNATE-SERVER from message.
- func (s *AlternateServer) GetFrom(m *Message) error {
- a := (*MappedAddress)(s)
- return a.GetFromAs(m, AttrAlternateServer)
- }
- func (a MappedAddress) String() string {
- return net.JoinHostPort(a.IP.String(), strconv.Itoa(a.Port))
- }
- // GetFromAs decodes MAPPED-ADDRESS value in message m as an attribute of type t.
- func (a *MappedAddress) GetFromAs(m *Message, t AttrType) error {
- v, err := m.Get(t)
- if err != nil {
- return err
- }
- if len(v) <= 4 {
- return io.ErrUnexpectedEOF
- }
- family := bin.Uint16(v[0:2])
- if family != familyIPv6 && family != familyIPv4 {
- return newDecodeErr("xor-mapped address", "family",
- fmt.Sprintf("bad value %d", family),
- )
- }
- ipLen := net.IPv4len
- if family == familyIPv6 {
- ipLen = net.IPv6len
- }
- // Ensuring len(a.IP) == ipLen and reusing a.IP.
- if len(a.IP) < ipLen {
- a.IP = a.IP[:cap(a.IP)]
- for len(a.IP) < ipLen {
- a.IP = append(a.IP, 0)
- }
- }
- a.IP = a.IP[:ipLen]
- for i := range a.IP {
- a.IP[i] = 0
- }
- a.Port = int(bin.Uint16(v[2:4]))
- copy(a.IP, v[4:])
- return nil
- }
- // AddToAs adds MAPPED-ADDRESS value to m as t attribute.
- func (a *MappedAddress) AddToAs(m *Message, t AttrType) error {
- var (
- family = familyIPv4
- ip = a.IP
- )
- if len(a.IP) == net.IPv6len {
- if isIPv4(ip) {
- ip = ip[12:16] // like in ip.To4()
- } else {
- family = familyIPv6
- }
- } else if len(ip) != net.IPv4len {
- return ErrBadIPLength
- }
- value := make([]byte, 128)
- value[0] = 0 // first 8 bits are zeroes
- bin.PutUint16(value[0:2], family)
- bin.PutUint16(value[2:4], uint16(a.Port))
- copy(value[4:], ip)
- m.Add(t, value[:4+len(ip)])
- return nil
- }
- // AddTo adds MAPPED-ADDRESS to message.
- func (a *MappedAddress) AddTo(m *Message) error {
- return a.AddToAs(m, AttrMappedAddress)
- }
- // GetFrom decodes MAPPED-ADDRESS from message.
- func (a *MappedAddress) GetFrom(m *Message) error {
- return a.GetFromAs(m, AttrMappedAddress)
- }
- // AddTo adds OTHER-ADDRESS attribute to message.
- func (o *OtherAddress) AddTo(m *Message) error {
- a := (*MappedAddress)(o)
- return a.AddToAs(m, AttrOtherAddress)
- }
- // GetFrom decodes OTHER-ADDRESS from message.
- func (o *OtherAddress) GetFrom(m *Message) error {
- a := (*MappedAddress)(o)
- return a.GetFromAs(m, AttrOtherAddress)
- }
- func (o OtherAddress) String() string {
- return net.JoinHostPort(o.IP.String(), strconv.Itoa(o.Port))
- }
- // AddTo adds RESPONSE-ORIGIN attribute to message.
- func (o *ResponseOrigin) AddTo(m *Message) error {
- a := (*MappedAddress)(o)
- return a.AddToAs(m, AttrResponseOrigin)
- }
- // GetFrom decodes RESPONSE-ORIGIN from message.
- func (o *ResponseOrigin) GetFrom(m *Message) error {
- a := (*MappedAddress)(o)
- return a.GetFromAs(m, AttrResponseOrigin)
- }
- func (o ResponseOrigin) String() string {
- return net.JoinHostPort(o.IP.String(), strconv.Itoa(o.Port))
- }
|