// Register a DNS Service of name, service type stype, with txt record specified, on // a certain port. This gets added to a list of registered services which can be // deregistered by calling ServiceDeregister(). I'm fairly sure that closing the program // causes the socket connection to mDNSResponder to be closed, which will also deregister // the services. func ServiceRegister(name, stype string, txt map[string]string, port uint16) error { txtblob, err := mapToBytes(txt) if err != nil { return err } // Network order is big-endian bport := (port&0xff)<<8 + port>>8 var ref C.DNSServiceRef dnserr := C.DNSServiceRegister( &ref, // DNSServiceRegister 0, // DNSServiceFlags 0, // Interface (0 => all interfaces) C.CString(name), // Service name (const char *) C.CString(stype), // Service type (const char *) nil, // Domain (const char *) empty => default domain nil, // Host (const char *), empty => machine default host C.uint16_t(bport), // Port, in network byte order C.uint16_t(len(txtblob)), // TXT Record length unsafe.Pointer(&txtblob[0]), // TXT Record nil, // Callback on register/fail (TODO: do something here) nil) // Application Context if dnserr != C.kDNSServiceErr_NoError { return errors.New("Could not register service") } services = append(services, ref) return nil }
func main() { counterChannel := make(chan int) go func() { counter := 0 for { <-time.After(1 * time.Second) fmt.Println("Counter at", counter) counterChannel <- counter counter++ } }() receivers := make([]chan int, 0) lock := new(sync.Mutex) go func() { for { counter := <-counterChannel lock.Lock() for _, receiver := range receivers { fmt.Println("Sending to receiver") receiver <- counter } lock.Unlock() } }() websocketHandler := func(ws *websocket.Conn) { fmt.Println("Received websocket connection") receiver := make(chan int) lock.Lock() receivers = append(receivers, receiver) lock.Unlock() for { value := <-receiver websocket.JSON.Send(ws, value) } } http.Handle("/ws", websocket.Handler(websocketHandler)) var listener net.Listener var err error if listener, err = net.Listen("tcp", "127.0.0.1:0"); err != nil { fmt.Println("Listen failed", err) return } var tcpAddr *net.TCPAddr if tcpAddr, err = net.ResolveTCPAddr("tcp", listener.Addr().String()); err != nil { fmt.Println("Couldn't resolve TCP address", err) return } fmt.Println("Listening on", fmt.Sprintf("http://localhost:%d", tcpAddr.Port)) // network order port := (tcpAddr.Port&0xff)<<8 | (tcpAddr.Port&0xff00)>>8 // Interface -1 means localhost var iface uint32 = 0 iface -= 1 serviceName := C.CString("woven") serviceType := C.CString("_woven._tcp") serviceDomain := C.CString("local.") var dnsRef C.DNSServiceRef if dnsErr := C.DNSServiceRegister(&dnsRef, 0, C.uint32_t(iface), serviceName, serviceType, serviceDomain, nil, C.uint16_t(port), 0, nil, nil, nil); dnsErr != 0 { fmt.Println("DNSServiceRegister failed", dnsErr) return } cleanup := func() { if dnsRef != nil { C.DNSServiceRefDeallocate(dnsRef) dnsRef = nil C.free(unsafe.Pointer(serviceDomain)) C.free(unsafe.Pointer(serviceType)) C.free(unsafe.Pointer(serviceName)) dnsRef = nil } } defer cleanup() signalChannel := make(chan os.Signal) signal.Notify(signalChannel, syscall.SIGTERM) signal.Notify(signalChannel, os.Interrupt) go func() { <-signalChannel cleanup() os.Exit(1) }() if err = http.Serve(listener, nil); err != nil { fmt.Println("Serve failed", err) return } }