aboutsummaryrefslogtreecommitdiff
path: root/list.go
blob: 102e10e68d471e8f62e7bca5b6aa9348ac457170 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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"] = protoVer
		a["proto_max"] = protoVer
		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.Println("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)
				}
			}
		}()
	}
}