initial commit

This commit is contained in:
Milarin 2024-02-15 17:09:59 +01:00
commit f280a09feb
4 changed files with 127 additions and 0 deletions

10
go.mod Normal file
View File

@ -0,0 +1,10 @@
module git.milar.in/milarin/sock
go 1.22.0
require (
git.milar.in/milarin/cmap v0.0.2
git.milar.in/milarin/slices v0.0.8
)
require git.milar.in/milarin/gmath v0.0.3 // indirect

6
go.sum Normal file
View File

@ -0,0 +1,6 @@
git.milar.in/milarin/cmap v0.0.2 h1:csO586l0G0+pi+7zR6tpblWEeMA6MDV3ix7B4GWsRiI=
git.milar.in/milarin/cmap v0.0.2/go.mod h1:OFU+P1CVPQqvQ6BC16qb+MK4IBPAdcY+EscNPHQ+n0k=
git.milar.in/milarin/gmath v0.0.3 h1:ii6rKNItS55O/wtIFhD1cTN2BMwDZjTBmiOocKURvxM=
git.milar.in/milarin/gmath v0.0.3/go.mod h1:HDLftG5RLpiNGKiIWh+O2G1PYkNzyLDADO8Cd/1abiE=
git.milar.in/milarin/slices v0.0.8 h1:qN9TE3tkArdTixMKSnwvNPcApwAjxpLVwA5a9k1rm2s=
git.milar.in/milarin/slices v0.0.8/go.mod h1:qMhdtMnfWswc1rHpwgNw33lB84aNEkdBn5BDiYA+G3k=

31
multiwriter.go Normal file
View File

@ -0,0 +1,31 @@
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 {
n, err = w.Write(p)
if err != nil || n != len(p) {
continue
}
}
return len(p), nil
}
func MultiWriter(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}
}

80
server.go Normal file
View File

@ -0,0 +1,80 @@
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
}