Skip to content
This repository was archived by the owner on Sep 29, 2018. It is now read-only.

Commit cbc78ec

Browse files
committed
Daemon Mode
1 parent b27423f commit cbc78ec

File tree

3 files changed

+167
-1
lines changed

3 files changed

+167
-1
lines changed

daemon.go

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"net"
7+
"os"
8+
"os/signal"
9+
"strings"
10+
"syscall"
11+
)
12+
13+
func runDaemon(base, datapath, logfile, socket string) {
14+
log, err := os.OpenFile(logfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
15+
if err != nil {
16+
panic(err)
17+
}
18+
defer log.Close()
19+
fmt.Fprintln(log, "Starting...")
20+
defer fmt.Fprintln(log, "Stopping...")
21+
sigs := make(chan os.Signal, 1)
22+
defer close(sigs)
23+
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
24+
l, err := net.Listen("unix", socket)
25+
if err != nil {
26+
panic(err)
27+
}
28+
defer l.Close()
29+
defer os.Remove(socket)
30+
exec := make(chan string)
31+
defer close(exec)
32+
conns := make(map[net.Conn]bool)
33+
newConns := make(chan net.Conn, 128)
34+
deadConns := make(chan net.Conn, 128)
35+
publishes := make(chan string, 128)
36+
done := make(chan struct{}, 1)
37+
defer func() {
38+
done <- struct{}{}
39+
}()
40+
go func() {
41+
for {
42+
c, err := l.Accept()
43+
if err != nil {
44+
break
45+
}
46+
newConns <- c
47+
}
48+
}()
49+
go func() {
50+
defer close(newConns)
51+
defer close(deadConns)
52+
defer close(publishes)
53+
defer close(done)
54+
outer:
55+
for {
56+
select {
57+
case c := <-newConns:
58+
conns[c] = true
59+
go func() {
60+
bs := bufio.NewScanner(c)
61+
for bs.Scan() {
62+
exec <- bs.Text()
63+
}
64+
deadConns <- c
65+
}()
66+
case c := <-deadConns:
67+
_ = c.Close()
68+
delete(conns, c)
69+
case text := <-publishes:
70+
for conn := range conns {
71+
go fmt.Fprintln(conn, text)
72+
}
73+
case <-done:
74+
break outer
75+
}
76+
}
77+
}()
78+
doLog := func(text string) {
79+
fmt.Fprintf(log, "%s\n", text)
80+
publishes <- text
81+
}
82+
for func() bool {
83+
f, quit := runImpl(base, datapath)
84+
defer f.Close()
85+
defer quit()
86+
status := make(chan bool)
87+
defer close(status)
88+
execFn := func(src, cmd string) {
89+
fmt.Fprintf(f, "%s\n", cmd)
90+
doLog(fmt.Sprintf("%s>%s", src, cmd))
91+
switch {
92+
case strings.HasPrefix(cmd, ":restart"):
93+
status <- true
94+
case strings.HasPrefix(cmd, ":quit"):
95+
status <- false
96+
}
97+
}
98+
cache := 0
99+
go packOutput(f, func(text string) {
100+
if strings.HasPrefix(text, "\x07") {
101+
execFn("mod", text[1:len(text)-1])
102+
cache++
103+
} else {
104+
if cache == 0 {
105+
doLog(fmt.Sprintf("\033[0m%s\033[0m", replacer.Replace(text)))
106+
} else {
107+
cache--
108+
}
109+
}
110+
})
111+
for {
112+
select {
113+
case x := <-status:
114+
return x
115+
case <-sigs:
116+
return false
117+
case line, ok := <-exec:
118+
if ok {
119+
cache++
120+
go execFn("socket", line)
121+
} else {
122+
return false
123+
}
124+
}
125+
}
126+
}() {
127+
doLog("Restarting...")
128+
}
129+
return
130+
}

main.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,41 @@ func (c *modsCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
159159
return subcommands.ExitSuccess
160160
}
161161

162+
type daemonCmd struct {
163+
bin string
164+
data string
165+
link string
166+
logfile string
167+
socket string
168+
}
169+
170+
func (*daemonCmd) Name() string { return "daemon" }
171+
func (*daemonCmd) Synopsis() string { return "Daemon" }
172+
func (*daemonCmd) Usage() string {
173+
return "daemon [-bin] [-data] [-link] [-daemon]\n\tRun server as daemon"
174+
}
175+
func (d *daemonCmd) SetFlags(f *flag.FlagSet) {
176+
f.StringVar(&d.data, "data", "data", "Minecraft Data Directory")
177+
f.StringVar(&d.bin, "bin", "bin", "Minecraft Server Binary Path")
178+
f.StringVar(&d.link, "link", "games", "World Link Path")
179+
f.StringVar(&d.logfile, "logfile", "games/mcpeserver.log", "Log File Path")
180+
f.StringVar(&d.socket, "socket", "games/mcpeserver.sock", "Socket File Path")
181+
}
182+
func (d *daemonCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) (ret subcommands.ExitStatus) {
183+
defer func() {
184+
if r := recover(); r != nil {
185+
fmt.Println("\033[5;91mError: \n", r)
186+
ret = subcommands.ExitFailure
187+
}
188+
}()
189+
d.data, _ = filepath.Abs(d.data)
190+
d.link, _ = filepath.Abs(d.link)
191+
d.bin, _ = filepath.Abs(d.bin)
192+
prepare(d.data, d.link)
193+
runDaemon(d.bin, d.data, d.logfile, d.socket)
194+
return subcommands.ExitSuccess
195+
}
196+
162197
type updateCmd struct {
163198
path string
164199
}
@@ -211,6 +246,7 @@ func main() {
211246
subcommands.Register(&downloadCmd{}, "")
212247
subcommands.Register(&unpackCmd{}, "")
213248
subcommands.Register(&runCmd{}, "")
249+
subcommands.Register(&daemonCmd{}, "")
214250
subcommands.Register(&updateCmd{}, "")
215251
subcommands.Register(&modsCmd{}, "")
216252
subcommands.Register(&versionCmd{}, "")

version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
package main
22

3-
var VERSION = "0.4.3"
3+
var VERSION = "0.5"

0 commit comments

Comments
 (0)