diff options
| -rw-r--r-- | example/.gitignore | 1 | ||||
| -rw-r--r-- | example/example.service | 9 | ||||
| -rw-r--r-- | example/example.socket | 8 | ||||
| -rw-r--r-- | example/main.go | 125 | ||||
| -rw-r--r-- | go.mod | 2 | ||||
| -rw-r--r-- | go.sum | 2 |
6 files changed, 147 insertions, 0 deletions
diff --git a/example/.gitignore b/example/.gitignore new file mode 100644 index 0000000..33a9488 --- /dev/null +++ b/example/.gitignore @@ -0,0 +1 @@ +example diff --git a/example/example.service b/example/example.service new file mode 100644 index 0000000..c02b755 --- /dev/null +++ b/example/example.service @@ -0,0 +1,9 @@ +[Unit] +Description=gosdd Example Service + +[Service] +Type=simple +ExecStart=%h/example + +[Install] +WantedBy=default.target diff --git a/example/example.socket b/example/example.socket new file mode 100644 index 0000000..467e437 --- /dev/null +++ b/example/example.socket @@ -0,0 +1,8 @@ +[Unit] +Description=gosdd Example Socket + +[Socket] +ListenStream=127.0.0.1:9999 + +[Install] +WantedBy=sockets.target diff --git a/example/main.go b/example/main.go new file mode 100644 index 0000000..66eace2 --- /dev/null +++ b/example/main.go @@ -0,0 +1,125 @@ +// This implements a simple example that can be tested on a machine +// running systemd. +package main + +import ( + "bufio" + "flag" + "fmt" + "log" + "net" + "os" + "os/signal" + "strings" + "sync" + + "golang.org/x/sys/unix" + + "go.awhk.org/gosdd" +) + +var useNames = flag.Bool("use-names", false, "whether to use SDListenFDsWithNames or not") + +func main() { + flag.Parse() + log.SetFlags(log.Lshortfile) + + if !*useNames { + fds, err := gosdd.SDListenFDs(true) + if err != nil { + log.Fatalln(err) + } + log.Printf("Received %d file descriptors from systemd.", len(fds)) + listenAll(fds) + return + } + + namedFDs, err := gosdd.SDListenFDsWithNames(true) + if err != nil { + log.Fatalln(err) + } + log.Printf("Received %d named file descriptors from systemd.", len(namedFDs)) + fds := make([]*os.File, 0, len(namedFDs)) + for name, fd := range namedFDs { + log.Printf("Adding %q.", name) + fds = append(fds, fd) + } + listenAll(fds) +} + +func listenAll(fds []*os.File) { + sig := make(chan os.Signal, 1) + signal.Notify(sig, os.Interrupt, unix.SIGTERM) + + srvs := make([]echoServer, 0, len(fds)) + wg := &sync.WaitGroup{} + for _, fd := range fds { + ln, err := net.FileListener(fd) + if err != nil { + log.Printf("Failed to make a listener: %s.", err) + continue + } + srv := echoServer{ln, wg} + srvs = append(srvs, srv) + go srv.start() + } + + <-sig + for _, srv := range srvs { + srv.stop() + } + wg.Wait() +} + +type echoServer struct { + ln net.Listener + wg *sync.WaitGroup +} + +func (*echoServer) handle(conn net.Conn) { + defer func() { + if err := conn.Close(); err != nil { + log.Println(err) + } + }() + + log.Printf("New connection, local address is %s, remote address is %s.", conn.LocalAddr(), conn.RemoteAddr()) + if _, err := fmt.Fprintln(conn, "Hello World!"); err != nil { + log.Println(err) + return + } + r := bufio.NewReader(conn) + for { + s, err := r.ReadString('\n') + if err != nil { + log.Println(err) + return + } + s = strings.Trim(s, "\n ") + log.Printf("Received %q.", s) + if _, err := fmt.Fprintf(conn, "You said %q!\n", s); err != nil { + log.Println(err) + return + } + } +} + +func (srv *echoServer) start() { + defer srv.wg.Done() + srv.wg.Add(1) + + for { + conn, err := srv.ln.Accept() + if err != nil { + log.Println(err) + return + } + go srv.handle(conn) + } +} + +func (srv *echoServer) stop() { + if err := srv.ln.Close(); err != nil { + log.Println(err) + } +} @@ -1,3 +1,5 @@ module go.awhk.org/gosdd go 1.16 + +require golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 @@ -0,0 +1,2 @@ +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
