func NewClient(conn Connection, options ...ClientOption) (*Client, error) {
	c := &Client{
		close:       make(chan struct{}),
		c:           conn,
		clock:       systemClock,
		rto:         int64(defaultRTO),
		rtoRate:     defaultTimeoutRate,
		t:           make(map[transactionID]*clientTransaction, 100),
		maxAttempts: defaultMaxAttempts,
		closeConn:   true,
	}
	for _, o := range options {
		o(c)
	}
	if c.c == nil {
		return nil, ErrNoConnection
	}
	if c.a == nil {
		c.a = NewAgent(nil)
	}
	if err := c.a.SetHandler(c.handleAgentCallback); err != nil {
		return nil, err
	}
	if c.collector == nil {
		c.collector = &tickerCollector{
			close: make(chan struct{}),
			clock: c.clock,
		}
	}
	if err := c.collector.Start(c.rtoRate, func(t time.Time) {
		closedOrPanic(c.a.Collect(t))
	}); err != nil {
		return nil, err
	}
	c.wg.Add(1)
	go c.readUntilClosed()
	runtime.SetFinalizer(c, clientFinalizer)
	return c, nil
}
NewClient initializes new Client from provided options,
starting internal goroutines and using default options fields
if necessary. Call Close method after using Client to close conn and
release resources.

The conn will be closed on Close call. Use WithNoConnClose option to
prevent that.

Note that user should handle the protocol multiplexing, client does not
provide any API for it, so if you need to read application data, wrap the
connection with your (de-)multiplexer and pass the wrapper as conn.
package stun
import (
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"runtime"
	"sync"
	"sync/atomic"
	"time"
)
func Dial(network, address string) (*Client, error) {
	conn, err := net.Dial(network, address)
	if err != nil {
		return nil, err
	}
	return NewClient(conn)
}
var ErrNoConnection = errors.New("no connection provided")
type ClientOption func(c *Client)
func WithHandler(h Handler) ClientOption {
	return func(c *Client) {
		c.handler = h
	}
}
func WithRTO(rto time.Duration) ClientOption {
	return func(c *Client) {
		c.rto = int64(rto)
	}
}
func WithClock(clock Clock) ClientOption {
	return func(c *Client) {
		c.clock = clock
	}
}
func WithTimeoutRate(d time.Duration) ClientOption {
	return func(c *Client) {
		c.rtoRate = d
	}
}
func WithAgent(a ClientAgent) ClientOption {
	return func(c *Client) {
		c.a = a
	}
}
func WithCollector(coll Collector) ClientOption {
	return func(c *Client) {
		c.collector = coll
	}
}
var WithNoConnClose ClientOption = func(c *Client) {
	c.closeConn = false
}
func WithNoRetransmit(c *Client) {
	c.maxAttempts = 0
	if c.rto == 0 {
		c.rto = defaultMaxAttempts * int64(defaultRTO)
	}
}
const (
	defaultTimeoutRate = time.Millisecond * 5
	defaultRTO         = time.Millisecond * 300
	defaultMaxAttempts = 7
)