aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.go15
-rw-r--r--list.go117
-rw-r--r--proxy.go1
-rw-r--r--run.go6
-rw-r--r--uptime.go10
5 files changed, 149 insertions, 0 deletions
diff --git a/config.go b/config.go
index 874c876..21bf2a1 100644
--- a/config.go
+++ b/config.go
@@ -43,6 +43,21 @@ type Config struct {
DropCSMRF bool
Groups map[string][]string
UserGroups map[string]string
+ List struct {
+ Enable bool
+ Addr string
+ Interval int
+
+ Name string
+ Desc string
+ URL string
+ Creative bool
+ Dmg bool
+ PvP bool
+ Game string
+ FarNames bool
+ Mods []string
+ }
}
// Conf returns a copy of the Config used by the proxy.
diff --git a/list.go b/list.go
new file mode 100644
index 0000000..bffee25
--- /dev/null
+++ b/list.go
@@ -0,0 +1,117 @@
+package proxy
+
+import (
+ "bytes"
+ "encoding/json"
+ "log"
+ "math"
+ "mime/multipart"
+ "net"
+ "net/http"
+ "net/textproto"
+ "sync"
+ "time"
+)
+
+const (
+ listAdd = "start"
+ listUpdate = "update"
+ listRm = "delete"
+)
+
+var announceMu sync.Mutex
+
+func announce(action string) error {
+ announceMu.Lock()
+ defer announceMu.Unlock()
+
+ addr, err := net.ResolveUDPAddr("udp", Conf().BindAddr)
+ if err != nil {
+ return err
+ }
+
+ a := map[string]interface{}{
+ "action": action,
+ "address": addr.IP.String(),
+ "port": addr.Port,
+ }
+
+ if action != listRm {
+ a["name"] = Conf().List.Name
+ a["description"] = Conf().List.Desc
+ a["version"] = versionString
+ a["proto_min"] = latestProtoVer
+ a["proto_max"] = latestProtoVer
+ a["url"] = Conf().List.URL
+ a["creative"] = Conf().List.Creative
+ a["damage"] = Conf().List.Dmg
+ a["password"] = Conf().RequirePasswd
+ a["pvp"] = Conf().List.PvP
+ a["uptime"] = math.Floor(Uptime().Seconds())
+ a["game_time"] = 0
+
+ playersMu.RLock()
+ a["clients"] = len(players)
+ clts := make([]string, 0, len(players))
+ for player := range players {
+ clts = append(clts, player)
+ }
+ playersMu.RUnlock()
+
+ a["clients_max"] = Conf().UserLimit
+ a["clients_list"] = clts
+ a["gameid"] = Conf().List.Game
+ }
+
+ if action == listAdd {
+ a["can_see_far_names"] = Conf().List.FarNames
+ a["mods"] = Conf().List.Mods
+ }
+
+ s, err := json.Marshal(a)
+ if err != nil {
+ return err
+ }
+
+ body := &bytes.Buffer{}
+ w := multipart.NewWriter(body)
+
+ header := textproto.MIMEHeader{}
+ header.Set("Content-Disposition", "form-data; name=\"json\"")
+
+ part, _ := w.CreatePart(header)
+ part.Write(s)
+ w.Close()
+
+ _, err = http.Post(Conf().List.Addr+"/announce", "multipart/form-data; boundary="+w.Boundary(), body)
+ if err != nil {
+ return err
+ }
+
+ log.Print("{←|⇶} announce ", action)
+ return nil
+}
+
+func init() {
+ if Conf().List.Enable {
+ go func() {
+ var added bool
+ t := time.NewTicker(time.Duration(Conf().List.Interval) * time.Second)
+ for {
+ <-t.C
+ if !added {
+ if err := announce(listAdd); err != nil {
+ log.Print("{←|⇶} ", err)
+ }
+
+ added = true
+ continue
+ }
+
+ if err := announce(listUpdate); err != nil {
+ log.Print("{←|⇶} ", err)
+ }
+ }
+ }()
+ }
+}
diff --git a/proxy.go b/proxy.go
index d7a03cc..c3da9d4 100644
--- a/proxy.go
+++ b/proxy.go
@@ -6,6 +6,7 @@ package proxy
const latestSerializeVer = 28
const latestProtoVer = 39
+const versionString = "5.5.0-dev-83a7b48bb"
const maxPlayerNameLen = 20
const playerNameChars = "^[a-zA-Z0-9-_]+$"
const bytesPerMediaBunch = 5000
diff --git a/run.go b/run.go
index 1a86a77..a11ffdb 100644
--- a/run.go
+++ b/run.go
@@ -49,6 +49,12 @@ func Run() {
signal.Notify(sig, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP)
<-sig
+ if Conf().List.Enable {
+ if err := announce(listRm); err != nil {
+ log.Print("{←|⇶} ", err)
+ }
+ }
+
clts := l.clients()
var wg sync.WaitGroup
diff --git a/uptime.go b/uptime.go
new file mode 100644
index 0000000..bbb085b
--- /dev/null
+++ b/uptime.go
@@ -0,0 +1,10 @@
+package proxy
+
+import "time"
+
+var startTime = time.Now()
+
+// Uptime returns the time the proxy has been running for
+func Uptime() time.Duration {
+ return time.Since(startTime)
+}