You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
2.6 KiB
118 lines
2.6 KiB
package common |
|
|
|
import ( |
|
"net" |
|
"fmt" |
|
"net/rpc" |
|
"os" |
|
"log" |
|
"os/signal" |
|
"syscall" |
|
"github.com/takama/daemon" |
|
) |
|
|
|
var Stdlog, Errlog *log.Logger |
|
|
|
type Server struct { |
|
daemon.Daemon |
|
Port string |
|
Name string |
|
Description string |
|
} |
|
|
|
// Manage by daemon commands or run the daemon |
|
func RunService(service Server, clientFn func() (string,error)) (string, error) { |
|
|
|
usage := "Usage: imaged install | remove | start | stop | status" |
|
|
|
// if received any kind of command, do it |
|
if len(os.Args) > 1 { |
|
command := os.Args[1] |
|
switch command { |
|
case "install": |
|
return service.Install() |
|
case "remove": |
|
return service.Remove() |
|
case "start": |
|
return service.Start() |
|
case "stop": |
|
return service.Stop() |
|
case "status": |
|
return service.Status() |
|
case "client": |
|
return clientFn() |
|
default: |
|
return usage, nil |
|
} |
|
} |
|
|
|
// Do something, call your goroutines, etc |
|
|
|
// Set up channel on which to send signal notifications. |
|
// We must use a buffered channel or risk missing the signal |
|
// if we're not ready to receive when the signal is sent. |
|
interrupt := make(chan os.Signal, 1) |
|
signal.Notify(interrupt, os.Interrupt, os.Kill, syscall.SIGTERM) |
|
|
|
// Set up listener for defined host and port |
|
listener, err := net.Listen("tcp", service.Port) |
|
if err != nil { |
|
return "Possibly was a problem with the port binding", err |
|
} |
|
|
|
// set up channel on which to send accepted connections |
|
listen := make(chan net.Conn, 100) |
|
go acceptConnection(listener, listen) |
|
defer func() { |
|
listener.Close() |
|
fmt.Println("Listener closed") |
|
}() |
|
|
|
rpc.Register(service) |
|
// loop work cycle with accept connections or interrupt |
|
// by system signal |
|
for { |
|
select { |
|
case conn := <-listen: |
|
go handleClient(conn) |
|
case killSignal := <-interrupt: |
|
Stdlog.Println("Got signal:", killSignal) |
|
Stdlog.Println("Stoping listening on ", listener.Addr()) |
|
listener.Close() |
|
if killSignal == os.Interrupt { |
|
return "Daemon was interruped by system signal", nil |
|
} |
|
return "Daemon was killed", nil |
|
} |
|
} |
|
|
|
// never happen, but need to complete code |
|
return usage, nil |
|
} |
|
|
|
// Accept a client connection and collect it in a channel |
|
func acceptConnection(listener net.Listener, listen chan<- net.Conn) { |
|
for { |
|
conn, err := listener.Accept() |
|
if err != nil { |
|
continue |
|
} |
|
listen <- conn |
|
} |
|
} |
|
|
|
func handleClient(client net.Conn) { |
|
Stdlog.Println("Got connection from: "+client.RemoteAddr().String()) |
|
|
|
// Close connection when this function ends |
|
defer func() { |
|
Stdlog.Println("Closing connection...") |
|
client.Close() |
|
}() |
|
rpc.ServeConn(client) |
|
} |
|
|
|
func init() { |
|
Stdlog = log.New(os.Stdout, "", log.Ldate|log.Ltime) |
|
Errlog = log.New(os.Stderr, "", log.Ldate|log.Ltime) |
|
} |