func (s *StunClient) allocateUnauthenticated() error {
	creds := s.Credentials
	s.Credentials = &stun.Credentials{}
	if err := s.send(goturn.NewAllocateRequest(s.Conn.RemoteAddr().Network(), false)); err != nil {
		return err
	}
	s.Credentials = creds
	response, err := s.readStunPacket()
	if err != nil {
		return err
	}
	if response.Credentials.Nonce != nil {
		s.Credentials.Nonce = response.Credentials.Nonce
	}
	if len(response.Credentials.Realm) > 0 {
		s.Credentials.Realm = response.Credentials.Realm
	}
	msgerr := stunattrs.GetError(response)
	if msgerr.Error() > 0 && msgerr.Error() != 401 {
		return errors.New("Initial Connection failed " + msgerr.String())
	}
	return nil
}
allocateUnauthenticated sends a TURN Allocate request (A request for
permission to send and receive data through the TURN server), but without
any credentials. By the RFC, this request must fail, but the error response
is used to populate the Nonce and Realm used by the server, so that subsequent
requests can be properly authenticated.
package client
import (
	"bufio"
	"errors"
	"github.com/willscott/goturn"
	"github.com/willscott/goturn/common"
	stunattrs "github.com/willscott/goturn/stun"
	turnattrs "github.com/willscott/goturn/turn"
	"net"
	"time"
)
type StunClient struct {
	net.Conn
	reader *bufio.Reader
	*net.Dialer
	*stun.Credentials
	Timeout time.Duration
	Deadline time.Time
}
func (s *StunClient) deriveConnection() (*StunClient, error) {
	other := new(StunClient)
	other.Dialer = s.Dialer
	other.Credentials = s.Credentials.ForNewConnection()
	other.Timeout = s.Timeout
	conn, err := s.Dialer.Dial(s.Conn.RemoteAddr().Network(), s.Conn.RemoteAddr().String())
	if err != nil {
		return nil, err
	}
	other.Conn = conn
	return other, nil
}
func (s *StunClient) send(packet *stun.Message, err error) error {
	if err != nil {
		return err
	}
	packet.Credentials = *s.Credentials
	message, err := packet.Serialize()
	if err != nil {
		return err
	}
	if _, err = s.Conn.Write(message); err != nil {
		return err
	}
	return nil
}
func (s *StunClient) readStunPacket() (*stun.Message, error) {
	if s.reader == nil {
		s.reader = bufio.NewReader(s.Conn)
	}
	if s.Timeout > 0 {
		if s.Deadline.IsZero() {
			s.Deadline = time.Now().Add(s.Timeout)
		}
		s.Conn.SetReadDeadline(s.Deadline)
	}
	h, err := s.reader.Peek(20)
	if err != nil {
		return nil, err
	}
	header := stun.Header{}
	if err = header.Decode(h); err != nil {
		return nil, err
	}
	if header.Length == 0 {
		return goturn.ParseTurn(h, s.Credentials)
	}
	if header.Length > 2048 {
		return nil, errors.New("Packet length too long.")
	}
	buffer := make([]byte, 20+header.Length)
	n, err := s.reader.Read(buffer)
	if err != nil || uint16(n) != 20+header.Length {
		return nil, err
	}
	if s.Timeout > 0 {
		s.Deadline = time.Now().Add(s.Timeout)
	}
	return goturn.ParseTurn(buffer, s.Credentials)
}
func (s *StunClient) Bind() (net.Addr, error) {
	packet, err := goturn.NewBindingRequest()
	if err != nil {
		return nil, err
	}
	message, err := packet.Serialize()
	if err != nil {
		return nil, err
	}
	if _, err = s.Conn.Write(message); err != nil {
		return nil, err
	}
	response, err := s.readStunPacket()
	if err != nil {
		return nil, err
	}
	if response.Header.Type != goturn.BindingResponse {
		return nil, errors.New("Unexpected response type.")
	}
	attr := response.GetAttribute(stunattrs.MappedAddress)
	port := uint16(0)
	address := net.IP{}
	if attr != nil {
		addr := (*attr).(*stunattrs.MappedAddressAttribute)
		port = addr.Port
		address = addr.Address
	} else {
		attr = response.GetAttribute(stunattrs.XorMappedAddress)
		if attr == nil {
			return nil, errors.New("No Mapped Address provided.")
		}
		addr := (*attr).(*stunattrs.XorMappedAddressAttribute)
		port = addr.Port
		address = addr.Address
	}
	return stun.NewAddress(s.Conn.RemoteAddr().Network(), address, port), nil
}