package sock import ( "io" "net" "os" "path/filepath" "git.milar.in/milarin/cmap" "git.milar.in/milarin/slices" ) type Server struct { socketPath string server net.Listener clients *cmap.Map[net.Conn, struct{}] } func Listen(socketPath string) (*Server, error) { absPath, err := filepath.Abs(socketPath) if err != nil { return nil, err } os.Remove(absPath) server, err := net.Listen("unix", absPath) if err != nil { return nil, err } s := &Server{ socketPath: absPath, server: server, clients: cmap.New[net.Conn, struct{}](), } go s.handleClients() return s, nil } func (s *Server) Broadcast(r io.Reader) error { clients := slices.Map(s.clients.Keys(), func(c net.Conn) io.Writer { return c }) w := MultiWriter(clients...) if _, err := io.Copy(w, r); err != nil { return err } return nil } func (s *Server) handleClients() { for client, err := s.server.Accept(); err == nil; client, err = s.server.Accept() { go s.handleClient(client) } } func (s *Server) handleClient(client net.Conn) { s.clients.Put(client, struct{}{}) defer s.clients.Delete(client) data := make([]byte, 1024) for _, err := client.Read(data); err == nil; _, err = client.Read(data) { } } func (s *Server) Close() error { if err := s.server.Close(); err != nil { return err } if err := os.Remove(s.socketPath); err != nil { return err } return nil }