func (c *Client) Close() {
	_ = c.conn.Close()
	c.tomb.Kill(ErrClientClosed)
}
Close will immediately close the client.
package broker
import (
	"errors"
	"sync"
	"sync/atomic"
	"time"
	"github.com/256dpi/gomqtt/packet"
	"github.com/256dpi/gomqtt/session"
	"github.com/256dpi/gomqtt/transport"
	"gopkg.in/tomb.v2"
)
type LogEvent string
const (
	NewConnection LogEvent = "new connection"
	PacketReceived LogEvent = "packet received"
	MessagePublished LogEvent = "message published"
	MessageAcknowledged LogEvent = "message acknowledged"
	MessageDequeued LogEvent = "message dequeued"
	MessageForwarded LogEvent = "message forwarded"
	PacketSent LogEvent = "packet sent"
	ClientDisconnected LogEvent = "client disconnected"
	TransportError LogEvent = "transport error"
	SessionError LogEvent = "session error"
	BackendError LogEvent = "backend error"
	ClientError LogEvent = "client error"
	LostConnection LogEvent = "lost connection"
)
type Session interface {
	NextID() packet.ID
	SavePacket(session.Direction, packet.Generic) error
	LookupPacket(session.Direction, packet.ID) (packet.Generic, error)
	DeletePacket(session.Direction, packet.ID) error
	AllPackets(session.Direction) ([]packet.Generic, error)
}
type Ack func()
type Backend interface {
	Authenticate(client *Client, user, password string) (ok bool, err error)
	Setup(client *Client, id string, clean bool) (a Session, resumed bool, err error)
	Restore(client *Client) error
	Subscribe(client *Client, subs []packet.Subscription, ack Ack) error
	Unsubscribe(client *Client, topics []string, ack Ack) error
	Publish(client *Client, msg *packet.Message, ack Ack) error
	Dequeue(client *Client) (*packet.Message, Ack, error)
	Terminate(client *Client) error
	Log(event LogEvent, client *Client, pkt packet.Generic, msg *packet.Message, err error)
}
var ErrUnexpectedPacket = errors.New("unexpected packet")
var ErrNotAuthorized = errors.New("not authorized")
var ErrMissingSession = errors.New("missing session")
var ErrTokenTimeout = errors.New("token timeout")
var ErrClientDisconnected = errors.New("client disconnected")
var ErrClientClosed = errors.New("client closed")
const (
	clientConnecting uint32 = iota
	clientConnected
	clientDisconnected
)
type Client struct {
	state uint32
	MaximumKeepAlive time.Duration
	ParallelPublishes int
	ParallelSubscribes int
	InflightMessages int
	TokenTimeout time.Duration
	PacketCallback func(packet.Generic) error
	Ref interface{}
	backend         Backend
	conn            transport.Conn
	id              string
	will            *packet.Message
	session         Session
	ackQueue        chan packet.Generic
	publishTokens   chan struct{}
	subscribeTokens chan struct{}
	dequeueTokens   chan struct{}
	tomb            tomb.Tomb
	closed          chan struct{}
}
func NewClient(backend Backend, conn transport.Conn) *Client {
	c := &Client{
		state:   clientConnecting,
		backend: backend,
		conn:    conn,
		closed:  make(chan struct{}),
	}
	c.tomb.Go(c.processor)
	go func() {
		_ = c.tomb.Wait()
		c.cleanup()
		close(c.closed)
	}()
	return c
}
func (c *Client) Session() Session {
	return c.session
}
func (c *Client) ID() string {
	return c.id
}
func (c *Client) Conn() transport.Conn {
	return c.conn
}