initial commit

This commit is contained in:
2025-07-31 18:34:16 +02:00
commit 8e4f8c2fcc
4 changed files with 135 additions and 0 deletions

12
go.mod Normal file
View File

@ -0,0 +1,12 @@
module git.tordarus.net/tordarus/sock
go 1.24.1
toolchain go1.24.5
require (
git.tordarus.net/tordarus/cmap v0.0.5
git.tordarus.net/tordarus/slices v0.0.15
)
require git.tordarus.net/tordarus/gmath v0.0.7 // indirect

6
go.sum Normal file
View File

@ -0,0 +1,6 @@
git.tordarus.net/tordarus/cmap v0.0.5 h1:g2STu3iMXCLn96JZ/f0iN5hbzct9cI5B8+V8ATB4ryE=
git.tordarus.net/tordarus/cmap v0.0.5/go.mod h1:Wx2snnIzdDrmONR9X5bt5aFq8E8EDCK5Zy50DmRwK1M=
git.tordarus.net/tordarus/gmath v0.0.7 h1:tR48idt9AUL0r556ww3ZxByTKJEr6NWCTlhl2ihzYxQ=
git.tordarus.net/tordarus/gmath v0.0.7/go.mod h1:mO7aPlvNrGVE9UFXEuuACjZgMDsM63l3OcQy6xSQnoE=
git.tordarus.net/tordarus/slices v0.0.15 h1:qxKS+7BCZ/LzQbRCvdDFoLQXaJZ2C0GfVju/kPt1r3g=
git.tordarus.net/tordarus/slices v0.0.15/go.mod h1:eJBw6pSDNivPI0l4e0sGKUJzou/lbzHflXdAUzp1g4o=

28
multiwriter.go Normal file
View File

@ -0,0 +1,28 @@
package sock
import "io"
type multiWriter struct {
writers []io.Writer
}
var _ io.Writer = &multiWriter{}
func (t *multiWriter) Write(p []byte) (n int, err error) {
for _, w := range t.writers {
w.Write(p)
}
return len(p), nil
}
func newMultiWriter(writers ...io.Writer) io.Writer {
allWriters := make([]io.Writer, 0, len(writers))
for _, w := range writers {
if mw, ok := w.(*multiWriter); ok {
allWriters = append(allWriters, mw.writers...)
} else {
allWriters = append(allWriters, w)
}
}
return &multiWriter{allWriters}
}

89
server.go Normal file
View File

@ -0,0 +1,89 @@
package sock
import (
"io"
"net"
"os"
"path/filepath"
"git.tordarus.net/tordarus/cmap"
"git.tordarus.net/tordarus/slices"
)
type Server struct {
socketPath string
server net.Listener
clients *cmap.Map[net.Conn, struct{}]
onNewClient func(client net.Conn)
}
func Listen(socketPath string, onNewClient func(client net.Conn)) (*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{}](),
onNewClient: onNewClient,
}
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 := newMultiWriter(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)
if s.onNewClient != nil {
s.onNewClient(client)
}
data := make([]byte, 1024)
for _, err := client.Read(data); err == nil; _, err = client.Read(data) {
}
}
func (s *Server) Close() error {
for client := range s.clients.Iterate() {
client.Close()
}
if err := s.server.Close(); err != nil {
return err
}
if err := os.Remove(s.socketPath); err != nil {
return err
}
return nil
}