func (t *tunListener) Close() error {
	t.Lock()
	defer t.Unlock()
	select {
	case <-t.closed:
		return nil
	default:
		t.delFunc()
		t.session.Close()
		close(t.closed)
	}
	return nil
}
Close closes tunnel listener
package mucp
import (
	"io"
	"sync"
	"github.com/micro/micro/v3/service/logger"
	"github.com/micro/micro/v3/service/network/tunnel"
)
type tunListener struct {
	channel string
	token string
	accept chan *session
	tunClosed chan bool
	session *session
	delFunc func()
	sync.RWMutex
	closed chan bool
}
func (t *tunListener) process() {
	conns := make(map[string]*session)
	defer func() {
		for id, conn := range conns {
			conn.Close()
			delete(conns, id)
		}
		conns = nil
	}()
	for {
		select {
		case <-t.closed:
			return
		case <-t.tunClosed:
			t.Close()
			return
		case m := <-t.session.recv:
			var sessionId string
			var linkId string
			switch t.session.mode {
			case tunnel.Multicast:
				sessionId = "multicast"
				linkId = "multicast"
			case tunnel.Broadcast:
				sessionId = "broadcast"
				linkId = "broadcast"
			default:
				sessionId = m.session
				linkId = m.link
			}
			sess, ok := conns[sessionId]
			if logger.V(logger.TraceLevel, log) {
				log.Tracef("Tunnel listener received channel %s session %s type %s exists: %t", m.channel, m.session, m.typ, ok)
			}
			if !ok {
				switch m.typ {
				case "open", "session":
				default:
					continue
				}
				sess = &session{
					key: []byte(t.token + m.channel + sessionId),
					tunnel: m.tunnel,
					channel: m.channel,
					session: sessionId,
					token: t.token,
					loopback: m.loopback,
					link: linkId,
					mode: t.session.mode,
					closed: make(chan bool),
					recv: make(chan *message, 128),
					send: t.session.send,
					errChan: make(chan error, 1),
					readTimeout: t.session.readTimeout,
				}
				conns[sessionId] = sess
				select {
				case <-t.closed:
					return
				case t.accept <- sess:
				}
			}
			switch m.typ {
			case "close":
				if sess.mode > tunnel.Unicast {
					continue
				}
				select {
				case <-sess.closed:
					delete(conns, sessionId)
				default:
					close(sess.closed)
					delete(conns, sessionId)
				}
				continue
			case "session":
			default:
				continue
			}
			select {
			case <-sess.closed:
				delete(conns, sessionId)
			case sess.recv <- m:
				if logger.V(logger.TraceLevel, log) {
					log.Tracef("Tunnel listener sent to recv chan channel %s session %s type %s", m.channel, sessionId, m.typ)
				}
			}
		}
	}
}
func (t *tunListener) Channel() string {
	return t.channel
}