Example #1
3
func UnixAudienceListener(sockaddr string) {
	fi, err := os.Stat(sockaddr)
	if err == nil {
		fmode := fi.Mode()
		if fmode&os.ModeType == os.ModeSocket {
			o.Warn("Removing stale socket at %s", sockaddr)
			os.Remove(sockaddr)
		} else {
			o.Fail("%s exists and is not a socket", sockaddr)
		}
	}
	laddr, err := net.ResolveUnixAddr("unix", sockaddr)
	o.MightFail(err, "Couldn't resolve audience socket address")
	l, err := net.ListenUnix("unix", laddr)
	o.MightFail(err, "Couldn't start audience unixsock listener")
	// Fudge the permissions on the unixsock!
	fi, err = os.Stat(sockaddr)
	if err == nil {
		os.Chmod(sockaddr, fi.Mode()|0777)
	} else {
		o.Warn("Couldn't fudge permission on audience socket: %s", err)
	}

	// make sure we clean up the unix socket when we die.
	defer l.Close()
	defer os.Remove(sockaddr)
	AudienceListener(l)
}
Example #2
0
func (self *UdpOutput) Init(pcf *plugins.PluginCommonConfig, conf toml.Primitive) error {
	var err error
	log.Println("UdpOutput Init.")
	self.config = &UdpOutputConfig{
		Net: "udp",
		// Defines maximum size of udp data for IPv4.
		MaxMessageSize: 65507,
	}
	if err := toml.PrimitiveDecode(conf, self.config); err != nil {
		return fmt.Errorf("Can't unmarshal UdpOutput config: %s", err)
	}
	if self.config.MaxMessageSize < 512 {
		return fmt.Errorf("Maximum message size can't be smaller than 512 bytes.")
	}
	if self.config.Net == "unixgram" {
		if runtime.GOOS == "windows" {
			return errors.New("Can't use Unix datagram sockets on Windows.")
		}
		var unixAddr, lAddr *net.UnixAddr
		unixAddr, err = net.ResolveUnixAddr(self.config.Net, self.config.Address)
		if err != nil {
			return fmt.Errorf("Error resolving unixgram address '%s': %s", self.config.Address,
				err.Error())
		}
		if self.config.LocalAddress != "" {
			lAddr, err = net.ResolveUnixAddr(self.config.Net, self.config.LocalAddress)
			if err != nil {
				return fmt.Errorf("Error resolving local unixgram address '%s': %s",
					self.config.LocalAddress, err.Error())
			}
		}
		if self.conn, err = net.DialUnix(self.config.Net, lAddr, unixAddr); err != nil {
			return fmt.Errorf("Can't connect to '%s': %s", self.config.Address,
				err.Error())
		}
	} else {
		var udpAddr, lAddr *net.UDPAddr
		if udpAddr, err = net.ResolveUDPAddr(self.config.Net, self.config.Address); err != nil {
			return fmt.Errorf("Error resolving UDP address '%s': %s", self.config.Address,
				err.Error())
		}
		if self.config.LocalAddress != "" {
			lAddr, err = net.ResolveUDPAddr(self.config.Net, self.config.LocalAddress)
			if err != nil {
				return fmt.Errorf("Error resolving local UDP address '%s': %s",
					self.config.Address, err.Error())
			}
		}
		if self.conn, err = net.DialUDP(self.config.Net, lAddr, udpAddr); err != nil {
			return fmt.Errorf("Can't connect to '%s': %s", self.config.Address,
				err.Error())
		}
	}

	return err
}
Example #3
0
// Initialize UDP connection
func (o *UdpOutput) Init(config interface{}) (err error) {
	o.UdpOutputConfig = config.(*UdpOutputConfig) // assert we have the right config type

	if o.UdpOutputConfig.MaxMessageSize < 512 {
		return fmt.Errorf("Maximum message size can't be smaller than 512 bytes.")
	}

	if o.Net == "unixgram" {
		if runtime.GOOS == "windows" {
			return errors.New("Can't use Unix datagram sockets on Windows.")
		}
		var unixAddr, lAddr *net.UnixAddr
		unixAddr, err = net.ResolveUnixAddr(o.Net, o.Address)
		if err != nil {
			return fmt.Errorf("Error resolving unixgram address '%s': %s", o.Address,
				err.Error())
		}
		if o.LocalAddress != "" {
			lAddr, err = net.ResolveUnixAddr(o.Net, o.LocalAddress)
			if err != nil {
				return fmt.Errorf("Error resolving local unixgram address '%s': %s",
					o.LocalAddress, err.Error())
			}
		}
		if o.conn, err = net.DialUnix(o.Net, lAddr, unixAddr); err != nil {
			return fmt.Errorf("Can't connect to '%s': %s", o.Address,
				err.Error())
		}
	} else {
		var udpAddr, lAddr *net.UDPAddr
		if udpAddr, err = net.ResolveUDPAddr(o.Net, o.Address); err != nil {
			return fmt.Errorf("Error resolving UDP address '%s': %s", o.Address,
				err.Error())
		}
		if o.LocalAddress != "" {
			lAddr, err = net.ResolveUDPAddr(o.Net, o.LocalAddress)
			if err != nil {
				return fmt.Errorf("Error resolving local UDP address '%s': %s",
					o.Address, err.Error())
			}
		}
		if o.conn, err = net.DialUDP(o.Net, lAddr, udpAddr); err != nil {
			return fmt.Errorf("Can't connect to '%s': %s", o.Address,
				err.Error())
		}
	}
	return
}
Example #4
0
func StartClientHandler(tree *ProcessTree, quit chan bool) {
	path, _ := filepath.Abs(zeusSockName)
	addr, err := net.ResolveUnixAddr("unix", path)
	if err != nil {
		panic("Can't open socket.")
	}
	listener, err := net.ListenUnix("unix", addr)
	if err != nil {
		ErrorCantCreateListener()
	}
	defer listener.Close()

	connections := make(chan *unixsocket.Usock)
	go func() {
		for {
			if conn, err := listener.AcceptUnix(); err != nil {
				errorUnableToAcceptSocketConnection()
				time.Sleep(500 * time.Millisecond)
			} else {
				connections <- unixsocket.NewUsock(conn)
			}
		}
	}()

	for {
		select {
		case <-quit:
			quit <- true
			return
		case conn := <-connections:
			go handleClientConnection(tree, conn)
		}
	}
}
Example #5
0
// Can have dup server address for higher weight
func (this *StandardServerSelector) SetServers(servers ...string) error {
	if len(servers) == 0 {
		return ErrNoServers
	}

	naddr := make([]net.Addr, len(servers))
	for i, server := range servers {
		if strings.Contains(server, "/") {
			addr, err := net.ResolveUnixAddr("unix", server)
			if err != nil {
				return err
			}
			naddr[i] = addr
		} else {
			tcpaddr, err := net.ResolveTCPAddr("tcp", server)
			if err != nil {
				return err
			}
			naddr[i] = tcpaddr
		}
	}

	this.lk.Lock()
	defer this.lk.Unlock()
	this.addrs = naddr
	return nil
}
Example #6
0
func unixDial(networ, addr string) (net.Conn, error) {
	var raddr *net.UnixAddr
	var err error
	if addr == "unix.socket:80" {
		raddr, err = net.ResolveUnixAddr("unix", shared.VarPath("unix.socket"))
		if err != nil {
			return nil, fmt.Errorf(gettext.Gettext("cannot resolve unix socket address: %v"), err)
		}
	} else { // TODO - I think this is dead code
		raddr, err = net.ResolveUnixAddr("unix", addr)
		if err != nil {
			return nil, fmt.Errorf(gettext.Gettext("cannot resolve unix socket address: %v"), err)
		}
	}
	return net.DialUnix("unix", nil, raddr)
}
Example #7
0
// Open opens the transport.
func (c Config) Open() (transports.Transport, error) {
	if c.Name == "" {
		c.Name = path.Join(os.TempDir(), "telehash-"+randomString(8)+".sock")
	}

	if c.Mode == 0 {
		c.Mode = 0700
	}
	c.Mode &= os.ModePerm
	c.Mode |= os.ModeSocket

	laddr, err := net.ResolveUnixAddr("unix", c.Name)
	if err != nil {
		return nil, err
	}

	listener, err := net.ListenUnix("unix", laddr)
	if err != nil {
		return nil, err
	}

	err = os.Chmod(laddr.Name, c.Mode)
	if err != nil {
		listener.Close()
		os.Remove(laddr.Name)
		return nil, err
	}

	return &transport{(*unixAddr)(laddr), listener}, nil
}
func (_ *ListenerSuite) TestListenUnix(c *C) {
	addr, _ := net.ResolveUnixAddr("unix", "/tmp/go_test_socket")
	cfg := &conf.ListenerConf{
		Name: "local",
		Ports: []*conf.PortConf{
			&conf.PortConf{
				Type: "unix",
				Addr: addr,
			},
		},
	}

	ll := listener.NewListener(cfg)
	ll.SetHandler(echoHandler)
	ll.Start()
	time.Sleep(50 * time.Millisecond)

	cc, err := net.DialUnix("unix", nil, addr)
	c.Assert(err, IsNil)

	testEchoConnection(c, cc)

	cc.Close()

	ll.Stop()
}
Example #9
0
func main() {
	path := "/tmp/example.sock"
	addr, err := net.ResolveUnixAddr("unixgram", path)
	if err != nil {
		fmt.Printf("ResolveUnixAddr err: %s\n", err)
		return
	}
	conn, err := net.ListenUnixgram("unixgram", addr)
	if err != nil {
		fmt.Printf("ListenUnixgram err: %s\n", err)
		return
	}

	// Ensure world writable access
	os.Chmod(path, 0666)

	data := make([]byte, 4096)

	length, _, err := conn.ReadFrom(data)
	if err != nil {
		fmt.Printf("conn.ReadFrom error: %s\n", err)
		return
	}

	fmt.Printf("Got: %d bytes\n", length)
}
func NewTServerUnixDomainTimeout(listenAddr string, clientTimeout time.Duration) (*TServerUnixDomain, error) {
	addr, err := net.ResolveUnixAddr("unix", listenAddr)
	if err != nil {
		return nil, err
	}
	return &TServerUnixDomain{addr: addr, clientTimeout: clientTimeout}, nil
}
Example #11
0
func serveFpr(addr string, s *siegfried.Siegfried) {
	// remove the socket file if it exists
	if _, err := os.Stat(addr); err == nil {
		os.Remove(addr)
	}
	uaddr, err := net.ResolveUnixAddr("unix", addr)
	if err != nil {
		log.Fatalf("FPR error: failed to get address: %v", err)
	}
	lis, err := net.ListenUnix("unix", uaddr)
	if err != nil {
		log.Fatalf("FPR error: failed to listen: %v", err)
	}
	buf := make([]byte, 4024)
	for {
		conn, err := lis.Accept()
		if err != nil {
			log.Fatalf("FPR error: bad connection: %v", err)
		}
		l, err := conn.Read(buf)
		if err != nil {
			conn.Write([]byte("error reading from connection: " + err.Error()))
		}
		conn.Write(fpridentify(s, string(buf[:l])))
		conn.Close()
	}
}
Example #12
0
func connectViaUnix(c *Client, remote *RemoteConfig) error {
	c.BaseURL = "http://unix.socket"
	c.BaseWSURL = "ws://unix.socket"
	c.Transport = "unix"
	uDial := func(network, addr string) (net.Conn, error) {
		// The arguments 'network' and 'addr' are ignored because
		// they are the wrong information.
		// addr is generated from BaseURL which becomes
		// 'unix.socket:80' which is certainly not what we want.
		// handle:
		//   unix:///path/to/socket
		//   unix:/path/to/socket
		//   unix:path/to/socket
		path := strings.TrimPrefix(remote.Addr, "unix:")
		if strings.HasPrefix(path, "///") {
			// translate unix:///path/to, to just "/path/to"
			path = path[2:]
		}
		raddr, err := net.ResolveUnixAddr("unix", path)
		if err != nil {
			return nil, err
		}
		return net.DialUnix("unix", nil, raddr)
	}
	c.Http.Transport = &http.Transport{Dial: uDial}
	c.websocketDialer.NetDial = uDial
	c.Remote = remote

	st, err := c.ServerStatus()
	if err != nil {
		return err
	}
	c.Certificate = st.Environment.Certificate
	return nil
}
Example #13
0
// StartUnixListener starts up a unix domain socket listener for reconnects to
// be sent through
func (irc *Bot) StartUnixListener() {
	unaddr, err := net.ResolveUnixAddr("unix", irc.unixastr)
	if err != nil {
		panic(err)
	}
	list, err := net.ListenUnix("unix", unaddr)
	if err != nil {
		panic(err)
	}

	irc.unixlist = list
	con, err := list.AcceptUnix()
	if err != nil {
		fmt.Println("unix listener error: ", err)
		return
	}
	list.Close()

	fi, err := irc.con.(*net.TCPConn).File()
	if err != nil {
		panic(err)
	}

	err = sendfd.SendFD(con, fi)
	if err != nil {
		panic(err)
	}

	select {
	case <-irc.Incoming:
	default:
		close(irc.Incoming)
	}
	close(irc.outgoing)
}
Example #14
0
func (s *Server) ListenAndServer() error {
	db, _ := OpenFile("/var/level/testdb", nil)
	hashDb, _ := OpenFile("/var/level/testhashdb", nil)

	var network string
	var (
		addr net.Addr
		err  error
	)
	if strings.Contains(s.Addr, "/") {
		network = "unix"
		addr, err = net.ResolveUnixAddr("unix", s.Addr)
	} else {
		network = "tcp"
		addr, err = net.ResolveTCPAddr("tcp", s.Addr)
	}
	if err != nil {
		return err
	}

	l, e := net.Listen(network, addr.String())
	if e != nil {
		return e
	}
	defer l.Close()
	for {
		rw, e := l.Accept()
		if e != nil {
			return e
		}
		c := s.newConn(rw)
		go c.serve(db, hashDb)
	}
}
Example #15
0
func (s *suite) TestSocketPathIsUnixAddr(c *gc.C) {
	path := socketpath()
	addr, err := net.ResolveUnixAddr("unix", path)
	c.Assert(err, gc.IsNil)
	c.Assert(addr.Name, gc.Equals, path)
	c.Assert(addr.Net, gc.Equals, "unix")
}
Example #16
0
// returns a new BusConnection.
func BusConnect(path string, bh busHandler, rh readHandler) (conn *BusConnection, err error) {

	// check if file exists. if not, bail.
	_, err = os.Lstat(path)
	if err != nil {
		return
	}

	// resolve the address.
	addr, err := net.ResolveUnixAddr("unix", path)
	if err != nil {
		return
	}

	// connect.
	unixConn, err := net.DialUnix("unix", nil, addr)
	if err != nil {
		return
	}

	// create the connection.
	conn = &BusConnection{
		path:        path,
		socket:      unixConn,
		incoming:    bufio.NewReader(unixConn),
		outgoing:    bufio.NewWriter(unixConn),
		busHandler:  bh,
		readHandler: rh,
		Connected:   true,
	}

	return
}
Example #17
0
func UnixAudienceListener(sockaddr string, sockmode os.FileMode, sockuid int, sockgid int) {
	fi, err := os.Stat(sockaddr)
	if err == nil {
		if (fi.Mode() & os.ModeSocket) != 0 {
			os.Remove(sockaddr)
		} else {
			o.Fail("%s exists and is not a socket", sockaddr)
		}
	}
	err = os.MkdirAll(path.Dir(sockaddr), 0755)
	o.MightFail(err, "Couldn't create socket directory")
	laddr, err := net.ResolveUnixAddr("unix", sockaddr)
	o.MightFail(err, "Couldn't resolve audience socket address")
	old_umask := syscall.Umask(0777)
	defer syscall.Umask(old_umask)
	l, err := net.ListenUnix("unix", laddr)
	o.MightFail(err, "Couldn't start audience unixsock listener")
	if sockuid >= 0 || sockgid >= 0 {
		err = os.Chown(sockaddr, sockuid, sockgid)
		o.MightFail(err, "Couldn't chown audience unixsock listener")
	}
	err = os.Chmod(sockaddr, sockmode)
	o.MightFail(err, "Couldn't chmod audience unixsock listener")

	// make sure we clean up the unix socket when we die.
	defer l.Close()
	defer os.Remove(sockaddr)
	AudienceListener(l)
}
Example #18
0
// Listen starts gorutine that receives syslog messages on specified address.
// addr can be a path (for unix domain sockets) or host:port (for UDP).
func (s *Server) Listen(addr string) error {
	var c net.PacketConn
	if strings.IndexRune(addr, ':') != -1 {
		a, err := net.ResolveUDPAddr("udp", addr)
		if err != nil {
			return err
		}
		c, err = net.ListenUDP("udp", a)
		if err != nil {
			return err
		}
	} else {
		a, err := net.ResolveUnixAddr("unixgram", addr)
		if err != nil {
			return err
		}
		c, err = net.ListenUnixgram("unixgram", a)
		if err != nil {
			return err
		}
	}
	s.conns = append(s.conns, c)
	go s.receiver(c)
	return nil
}
Example #19
0
func (s *UnixListenerTestSuite) TestSendAndUnmarshalConnData() {
	if !s.NoError(s.Listener.Start(), "should start successfully") {
		return
	}

	in := map[string]string{
		"foo": "bar",
	}

	addr, _ := net.ResolveUnixAddr("unix", s.Listener.Addr())
	conn, err := net.DialUnix("unix", nil, addr)
	if !s.NoError(err, "failed to dial listener") {
		return
	}
	_ = acomm.SendConnData(conn, in)
	_ = conn.Close()

	lConn := s.Listener.NextConn()
	if !s.NotNil(lConn, "connection should not be nil") {
		return
	}

	out := map[string]string{}
	s.NoError(acomm.UnmarshalConnData(lConn, &out), "should succeed unmarshalling")

	s.Equal(in, out, "should have unmarshaled the correct data")

	s.Listener.DoneConn(lConn)
}
Example #20
0
func main() {
	if len(os.Args) != 2 {
		println("need one argument")
		return
	}
	ua, err := net.ResolveUnixAddr("unix", os.Args[1])
	if err != nil {
		println("resolve unix", err.Error())
		return
	}
	ul, err := net.ListenUnix("unix", ua)
	if err != nil {
		println("listen unix", err.Error())
		return
	}
	//for {
	uc, err := ul.AcceptUnix()
	if err != nil {
		println("accept", err.Error())
		panic("accept")
	}
	go func() {
		r := rand.Int()
		for {
			uc.Write([]byte(fmt.Sprintf("%d\n", r)))
			time.Sleep(time.Second)
		}
	}()
	//}
	ul.Close()
	<-(chan int)(nil)
}
Example #21
0
func (p *Proxy) Listen() error {
	err := p.cleanup()
	if err != nil {
		return err
	}

	addr, err := net.ResolveUnixAddr("unix", "/var/run/docker.sock")
	if err != nil {
		return err
	}

	raw, err := net.ListenUnix("unix", addr)
	if err != nil {
		return err
	}

	listener := &stoppableListener{
		UnixListener: raw,
		done:         p.done,
	}

	err = os.Chmod("/var/run/docker.sock", 0777)
	if err != nil {
		return err
	}

	server := http.Server{
		Handler: http.HandlerFunc(p.handler),
	}

	return server.Serve(listener)
}
Example #22
0
func runFDForward(cCmd *cobra.Command, args []string) (exit int) {
	if len(args) != 1 {
		stderr("Provide a single argument")
		return 1
	}

	to := args[0]

	raddr, err := net.ResolveUnixAddr("unix", to)
	if err != nil {
		stderr("Unable to use %q as unix address: %v", to, err)
		return 1
	}

	sock, err := net.DialUnix("unix", nil, raddr)
	if err != nil {
		stderr("Failed dialing remote address: %v", err)
		return
	}
	defer sock.Close()

	errchan := make(chan error)
	go cp(os.Stdout, sock, errchan)
	go cp(sock, os.Stdin, errchan)

	select {
	case err := <-errchan:
		if err != nil {
			stderr("Encountered error during copy: %v", err)
			return 1
		}
	}

	return
}
Example #23
0
func main() {
	flag.Parse()

	// Create unix socket
	addr, err := net.ResolveUnixAddr("unix", *socketPath)
	if err != nil {
		log.Fatal(err)
	}
	l, err := net.ListenUnix("unix", addr)
	if err != nil {
		log.Fatal(err)
	}

	// Create server that listens on the socket
	s := agent.NewServer(l, &accpeter{})

	// Setup signal handler to stop Server on various signals
	s.StopOnSignals(os.Interrupt, syscall.SIGTERM)

	log.Println("Server listening on", addr.String())
	err = s.Serve()
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Server stopped")
}
Example #24
0
// listen and run
func ListenAndServe(addr string) error {
	var netaddr net.Addr
	var err error
	if strings.Contains(addr, "/") {
		netaddr, err = net.ResolveUnixAddr("unix", addr)
		if err != nil {
			return err
		}
	} else {
		netaddr, err = net.ResolveTCPAddr("tcp", addr)
		if err != nil {
			return err
		}
	}
	// listen
	l, err := net.Listen(netaddr.Network(), netaddr.String())
	if err != nil {
		return err
	}
	// same with ServeRpc
	http.Handle(GetRpcPath(codecName), &rpcHandler{NewServerCodec})

	err = http.Serve(l, nil)
	return err
}
Example #25
0
File: rsync.go Project: vahe/lxd
// Netcat is called with:
//
//    lxd netcat /path/to/unix/socket
//
// and does unbuffered netcatting of to socket to stdin/stdout. Any arguments
// after the path to the unix socket are ignored, so that this can be passed
// directly to rsync as the sync command.
func Netcat(args []string) error {
	if len(args) < 2 {
		return fmt.Errorf("Bad arguments %q", args)
	}

	uAddr, err := net.ResolveUnixAddr("unix", args[1])
	if err != nil {
		return err
	}

	conn, err := net.DialUnix("unix", nil, uAddr)
	if err != nil {
		return err
	}

	wg := sync.WaitGroup{}
	wg.Add(1)

	go func() {
		io.Copy(os.Stdout, conn)
		conn.Close()
		wg.Done()
	}()

	go func() {
		io.Copy(conn, os.Stdin)
	}()

	wg.Wait()

	return nil
}
Example #26
0
func ServerAddr(addr string) (net.Addr, error) {
	if strings.Contains(addr, "/") {
		return net.ResolveUnixAddr("unix", addr)
	} else {
		return net.ResolveTCPAddr("tcp", addr)
	}
}
Example #27
0
func (t *UnixInput) Init(config interface{}) error {
	var err error
	t.config = config.(*UnixInputConfig)
	if !strings.HasPrefix(t.config.Address, "@") {
		return fmt.Errorf("only ephemeral sockets supported - prefix your path with '@'")
	}
	address, err := net.ResolveUnixAddr("unix", t.config.Address)
	if err != nil {
		return fmt.Errorf("ResolveUnixAddress failed: %s\n", err.Error())
	}
	t.listener, err = net.ListenUnix("unix", address)
	if err != nil {
		return fmt.Errorf("ListenUnix failed: %s\n", err.Error())
	}
	// We're already listening, make sure we clean up if init fails later on.
	closeIt := true
	defer func() {
		if closeIt {
			t.listener.Close()
		}
	}()
	t.stopChan = make(chan bool)
	closeIt = false
	return nil
}
Example #28
0
// ParseAddr parses an address description into an address.
// If the description starts with "unix:", the result will be a Unix domain
// socket address with the path being the rest of the description string.
// Otherwise, the result will be a TCP address represented by the whole
// description string.
func ParseAddr(description string) (net.Addr, error) {
	if strings.HasPrefix(description, "unix:") {
		return net.ResolveUnixAddr("unix", description[len("unix:"):])
	} else {
		return net.ResolveTCPAddr("tcp", description)
	}
}
Example #29
0
func (s *Server) Start() error {
	c, _ := projects.ConfigDir()
	socketpath := filepath.Join(c, "projects.socket")

	addr, err := net.ResolveUnixAddr("unix", socketpath)

	if err != nil {
		return err
	}

	listener, e := net.ListenUnix("unix", addr)
	if e != nil {
		return e
	}

	var opts []grpc.ServerOption

	grpcServer := grpc.NewServer(opts...)
	messages.RegisterProjectsServer(grpcServer, &projectServer{s.core})
	messages.RegisterResourcesServer(grpcServer, &resourcesServer{s.core})
	messages.RegisterEventsServer(grpcServer, &eventsServer{s.core})
	//s.core.Log.Infof("project daemon started and listening on %s", socketpath)
	s.server = grpcServer
	s.listener = listener

	s.tomb.Go(func() error { return grpcServer.Serve(listener) })
	return nil
}
Example #30
0
File: socket.go Project: bac/juju
// NewWorker starts an http server listening on an abstract domain socket
// which will be created with the specified name.
func NewWorker(config Config) (worker.Worker, error) {
	if err := config.Validate(); err != nil {
		return nil, errors.Trace(err)
	}
	if runtime.GOOS != "linux" {
		return nil, errors.NotSupportedf("os %q", runtime.GOOS)
	}

	path := "@" + config.SocketName
	addr, err := net.ResolveUnixAddr("unix", path)
	if err != nil {
		return nil, errors.Annotate(err, "unable to resolve unix socket")
	}

	l, err := net.ListenUnix("unix", addr)
	if err != nil {
		return nil, errors.Annotate(err, "unable to listen on unix socket")
	}
	logger.Debugf("introspection worker listening on %q", path)

	w := &socketListener{
		listener: l,
		reporter: config.Reporter,
		done:     make(chan struct{}),
	}
	go w.serve()
	go w.run()
	return w, nil
}