func (c *candidateBase) close() error {
	if c.conn != nil {
		close(c.closeCh)
		err := c.conn.Close()
		if err != nil {
			return err
		}
		<-c.closedCh
	}
	return nil
}
close stops the recvLoop
package ice
import (
	"fmt"
	"net"
	"sync/atomic"
	"time"
	"github.com/pion/logging"
	"github.com/pion/stun"
)
type candidateBase struct {
	id            string
	networkType   NetworkType
	candidateType CandidateType
	component      uint16
	address        string
	port           int
	relatedAddress *CandidateRelatedAddress
	resolvedAddr *net.UDPAddr
	lastSent     atomic.Value
	lastReceived atomic.Value
	conn         net.PacketConn
	currAgent *Agent
	closeCh   chan struct{}
	closedCh  chan struct{}
}
func (c *candidateBase) ID() string {
	return c.id
}
func (c *candidateBase) Address() string {
	return c.address
}
func (c *candidateBase) Port() int {
	return c.port
}
func (c *candidateBase) Type() CandidateType {
	return c.candidateType
}
func (c *candidateBase) NetworkType() NetworkType {
	return c.networkType
}
func (c *candidateBase) Component() uint16 {
	return c.component
}
func (c *candidateBase) LocalPreference() uint16 {
	return defaultLocalPreference
}
func (c *candidateBase) RelatedAddress() *CandidateRelatedAddress {
	return c.relatedAddress
}
func (c *candidateBase) start(a *Agent, conn net.PacketConn) {
	c.currAgent = a
	c.conn = conn
	c.closeCh = make(chan struct{})
	c.closedCh = make(chan struct{})
	go c.recvLoop()
}
func (c *candidateBase) recvLoop() {
	defer func() {
		close(c.closedCh)
	}()
	log := c.agent().log
	buffer := make([]byte, receiveMTU)
	for {
		n, srcAddr, err := c.conn.ReadFrom(buffer)
		if err != nil {
			return
		}
		handleInboundCandidateMsg(c, buffer[:n], srcAddr, log)
	}
}
func handleInboundCandidateMsg(c Candidate, buffer []byte, srcAddr net.Addr, log logging.LeveledLogger) {
	if stun.IsMessage(buffer) {
		m := &stun.Message{
			Raw: make([]byte, len(buffer)),
		}
		copy(m.Raw, buffer)
		if err := m.Decode(); err != nil {
			log.Warnf("Failed to handle decode ICE from %s to %s: %v", c.addr(), srcAddr, err)
			return
		}
		err := c.agent().run(func(agent *Agent) {
			agent.handleInbound(m, c, srcAddr)
		})
		if err != nil {
			log.Warnf("Failed to handle message: %v", err)
		}
		return
	}
	isValidRemoteCandidate := make(chan bool, 1)
	err := c.agent().run(func(agent *Agent) {
		isValidRemoteCandidate <- agent.noSTUNSeen(c, srcAddr)
	})
	if err != nil {
		log.Warnf("Failed to handle message: %v", err)
	} else if !<-isValidRemoteCandidate {
		log.Warnf("Discarded message from %s, not a valid remote candidate", c.addr())
	}
	if _, err := c.agent().buffer.Write(buffer); err != nil {
		log.Warnf("failed to write packet")
	}
}