func (s *server) handleQuestion(q dns.Question, resp *dns.Msg) error {
	if s.service == nil {
		return nil
	}
	switch q.Name {
	case s.service.ServiceName():
		s.composeBrowsingAnswers(resp, 3200)
	case s.service.ServiceInstanceName():
		s.composeLookupAnswers(resp, 3200)
	}
	return nil
}
handleQuestion is used to handle an incoming question
package bonjour
import (
	"fmt"
	"log"
	"math/rand"
	"net"
	"os"
	"strings"
	"sync"
	"time"
	"github.com/socketplane/socketplane/Godeps/_workspace/src/github.com/miekg/dns"
	"github.com/socketplane/socketplane/Godeps/_workspace/src/golang.org/x/net/ipv4"
	"github.com/socketplane/socketplane/Godeps/_workspace/src/golang.org/x/net/ipv6"
)
var (
	mdnsGroupIPv4 = net.IPv4(224, 0, 0, 251)
	mdnsGroupIPv6 = net.ParseIP("ff02::fb")
	mdnsWildcardAddrIPv4 = &net.UDPAddr{
		IP:   net.ParseIP("224.0.0.0"),
		Port: 5353,
	}
	mdnsWildcardAddrIPv6 = &net.UDPAddr{
		IP:   net.ParseIP("[ff02::]"),
		Port: 5353,
	}
	ipv4Addr = &net.UDPAddr{
		IP:   mdnsGroupIPv4,
		Port: 5353,
	}
	ipv6Addr = &net.UDPAddr{
		IP:   mdnsGroupIPv6,
		Port: 5353,
	}
	serverCache = make(map[string]*server)
)
func Register(instance, service, domain string, port int, text []string, iface *net.Interface,
	bindToIntf bool) (chan<- bool, error) {
	entry := NewServiceEntry(instance, service, domain)
	entry.Port = port
	entry.Text = text
	if entry.Instance == "" {
		return nil, fmt.Errorf("Missing service instance name")
	}
	if entry.Service == "" {
		return nil, fmt.Errorf("Missing service name")
	}
	if entry.Domain == "" {
		entry.Domain = "local"
	}
	if entry.Port == 0 {
		return nil, fmt.Errorf("Missing port")
	}
	var err error
	if entry.HostName == "" {
		entry.HostName, err = os.Hostname()
		if err != nil {
			return nil, fmt.Errorf("Could not determine host")
		}
	}
	entry.HostName = fmt.Sprintf("%s.", trimDot(entry.HostName))
	if iface == nil && bindToIntf {
		iface = InterfaceToBind()
	}
	if iface == nil {
		addrs, err := net.LookupIP(entry.HostName)
		if err != nil {
			tmpHostName := fmt.Sprintf("%s%s.", entry.HostName, entry.Domain)
			addrs, err = net.LookupIP(tmpHostName)
			if err != nil {
				intAddrs, err := net.InterfaceAddrs()
				if err != nil {
					return nil, err
				}
				for _, a := range intAddrs {
					if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
						addrs = append(addrs, ipnet.IP)
					}
				}
				if len(addrs) == 0 {
					return nil, fmt.Errorf("Could not determine host IP addresses for %s", entry.HostName)
				}
			}
		}
		for i := 0; i < len(addrs); i++ {
			if ipv4 := addrs[i].To4(); ipv4 != nil {
				entry.AddrIPv4 = addrs[i]
			} else if ipv6 := addrs[i].To16(); ipv6 != nil {
				entry.AddrIPv6 = addrs[i]
			}
		}
	} else {
		addrs, err := iface.Addrs()
		if err == nil {
			for i := 0; i < len(addrs); i++ {
				addr := addrs[i].String()
				addr = strings.Split(addr, "/")[0]
				ip := net.ParseIP(addr)
				if ip != nil {
					if ip.To4() != nil {
						entry.AddrIPv4 = ip
					} else if ip.To16() != nil {
						entry.AddrIPv6 = ip
					}
				}
			}
		}
	}
	ifaceName := ""
	if iface != nil {
		ifaceName = iface.Name
	}
	s, ok := serverCache[ifaceName]
	if !ok {
		var err error
		s, err = newServer(iface)
		if err != nil {
			return nil, err
		}
		serverCache[ifaceName] = s
		go s.mainloop()
	}
	s.service = entry
	go s.probe()
	return s.shutdownCh, nil
}
func RegisterProxy(instance, service, domain string, port int, host, ip string, text []string, iface *net.Interface) (chan<- bool, error) {
	entry := NewServiceEntry(instance, service, domain)
	entry.Port = port
	entry.Text = text
	entry.HostName = host
	if entry.Instance == "" {
		return nil, fmt.Errorf("Missing service instance name")
	}
	if entry.Service == "" {
		return nil, fmt.Errorf("Missing service name")
	}
	if entry.HostName == "" {
		return nil, fmt.Errorf("Missing host name")
	}
	if entry.Domain == "" {
		entry.Domain = "local"
	}
	if entry.Port == 0 {
		return nil, fmt.Errorf("Missing port")
	}
	if !strings.HasSuffix(trimDot(entry.HostName), entry.Domain) {
		entry.HostName = fmt.Sprintf("%s.%s.", trimDot(entry.HostName), trimDot(entry.Domain))
	}
	ipAddr := net.ParseIP(ip)
	if ipAddr == nil {
		return nil, fmt.Errorf("Failed to parse given IP: %v", ip)
	} else if ipv4 := ipAddr.To4(); ipv4 != nil {
		entry.AddrIPv4 = ipAddr
	} else if ipv6 := ipAddr.To16(); ipv6 != nil {
		entry.AddrIPv4 = ipAddr
	} else {
		return nil, fmt.Errorf("The IP is neither IPv4 nor IPv6: %#v", ipAddr)
	}
	s, err := newServer(iface)
	if err != nil {
		return nil, err
	}
	s.service = entry
	go s.mainloop()
	go s.probe()
	return s.shutdownCh, nil
}
type server struct {
	service        *ServiceEntry
	ipv4conn       *net.UDPConn
	ipv6conn       *net.UDPConn
	shouldShutdown bool
	shutdownCh     chan bool
	shutdownLock   sync.Mutex
}
func newServer(iface *net.Interface) (*server, error) {
	ipv4conn, err := net.ListenMulticastUDP("udp4", iface, mdnsWildcardAddrIPv4)
	if err != nil {
		log.Printf("[ERR] bonjour: Failed to bind to udp4 port: %v", err)
	}
	ipv6conn, err := net.ListenMulticastUDP("udp6", iface, mdnsWildcardAddrIPv6)
	if ipv4conn == nil && ipv6conn == nil {
		return nil, fmt.Errorf("[ERR] bonjour: Failed to bind to any udp port!")
	}
	p1 := ipv4.NewPacketConn(ipv4conn)
	p2 := ipv6.NewPacketConn(ipv6conn)
	if iface != nil {
		errCount := 0
		if err := p1.JoinGroup(iface, &net.UDPAddr{IP: mdnsGroupIPv4}); err != nil {
			errCount++
		}
		if err := p2.JoinGroup(iface, &net.UDPAddr{IP: mdnsGroupIPv6}); err != nil {
			errCount++
		}
		if errCount == 2 {
			return nil, fmt.Errorf("Failed to join multicast group on both v4 and v6")
		}
	} else {
		ifaces, err := net.Interfaces()
		if err != nil {
			return nil, err
		}
		errCount1, errCount2 := 0, 0
		for _, iface := range ifaces {
			if err := p1.JoinGroup(&iface, &net.UDPAddr{IP: mdnsGroupIPv4}); err != nil {
				errCount1++
			}
			if err := p2.JoinGroup(&iface, &net.UDPAddr{IP: mdnsGroupIPv6}); err != nil {
				errCount2++
			}
		}
		if len(ifaces) == errCount1 && len(ifaces) == errCount2 {
			return nil, fmt.Errorf("Failed to join multicast group on all interfaces!")
		}
	}
	s := &server{
		ipv4conn:   ipv4conn,
		ipv6conn:   ipv6conn,
		shutdownCh: make(chan bool),
	}
	return s, nil
}
func (s *server) mainloop() {
	if s.ipv4conn != nil {
		go s.recv(s.ipv4conn)
	}
	if s.ipv6conn != nil {
		go s.recv(s.ipv6conn)
	}
	for !s.shouldShutdown {
		select {
		case <-s.shutdownCh:
			s.shutdown()
		}
	}
}
func (s *server) shutdown() error {
	s.shutdownLock.Lock()
	defer s.shutdownLock.Unlock()
	s.unregister()
	if s.shouldShutdown {
		return nil
	}
	s.shouldShutdown = true
	close(s.shutdownCh)
	if s.ipv4conn != nil {
		s.ipv4conn.Close()
	}
	if s.ipv6conn != nil {
		s.ipv6conn.Close()
	}
	return nil
}
func (s *server) recv(c *net.UDPConn) {
	if c == nil {
		return
	}
	buf := make([]byte, 65536)
	for !s.shouldShutdown {
		n, from, err := c.ReadFrom(buf)
		if err != nil {
			continue
		}
		if err := s.parsePacket(buf[:n], from); err != nil {
			log.Printf("[ERR] bonjour: Failed to handle query: %v", err)
		}
	}
}
func (s *server) parsePacket(packet []byte, from net.Addr) error {
	var msg dns.Msg
	if err := msg.Unpack(packet); err != nil {
		log.Printf("[ERR] bonjour: Failed to unpack packet: %v", err)
		return err
	}
	return s.handleQuery(&msg, from)
}
func (s *server) handleQuery(query *dns.Msg, from net.Addr) error {
	if len(query.Answer) > 0 {
		return nil
	}
	if len(query.Ns) > 0 {
		return nil
	}
	var (
		resp dns.Msg
		err  error
	)
	if len(query.Question) > 0 {
		for i, _ := range query.Question {
			resp = dns.Msg{}
			resp.SetReply(query)
			resp.Answer = []dns.RR{}
			resp.Extra = []dns.RR{}
			if err = s.handleQuestion(query.Question[i], &resp); err != nil {
				log.Printf("[ERR] bonjour: failed to handle question %v: %v",
					query.Question[i], err)
				continue
			}
			if len(resp.Answer) > 0 {
				if e := s.multicastResponse(&resp); e != nil {
					err = e
				}
			}
		}
	}
	return err
}