/
main.go
153 lines (123 loc) · 3.81 KB
/
main.go
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package main
import (
"encoding/json"
"flag"
"net/http"
"os"
"time"
"github.com/getlantern/autoupdate-server/server"
"github.com/getlantern/golog"
)
var (
flagPrivateKey = flag.String("k", "", "Path to private key.")
flagLocalAddr = flag.String("l", ":6868", "Local bind address.")
flagPublicAddr = flag.String("p", "http://127.0.0.1:6868/", "Public address.")
flagGithubOrganization = flag.String("o", "getlantern", "Github organization.")
flagGithubProject = flag.String("n", "lantern", "Github project name.")
flagHelp = flag.Bool("h", false, "Shows help.")
)
var (
log = golog.LoggerFor("autoupdate-server")
releaseManager *server.ReleaseManager
)
type updateHandler struct {
}
// updateAssets checks for new assets released on the github releases page.
func updateAssets() error {
log.Debug("Updating assets...")
if err := releaseManager.UpdateAssetsMap(); err != nil {
return err
}
return nil
}
// backgroundUpdate periodically looks for releases.
func backgroundUpdate() {
for {
time.Sleep(githubRefreshTime)
// Updating assets...
if err := updateAssets(); err != nil {
log.Debugf("updateAssets: %s", err)
}
}
}
func (u *updateHandler) closeWithStatus(w http.ResponseWriter, status int) {
w.WriteHeader(status)
if _, err := w.Write([]byte(http.StatusText(status))); err != nil {
log.Debugf("Unable to write status: %v", err)
}
}
func (u *updateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var err error
var res *server.Result
if r.Method == "POST" {
defer func() {
if err := r.Body.Close(); err != nil {
log.Debugf("Unable to close request body: %v", err)
}
}()
var params server.Params
decoder := json.NewDecoder(r.Body)
if err = decoder.Decode(¶ms); err != nil {
u.closeWithStatus(w, http.StatusBadRequest)
return
}
if res, err = releaseManager.CheckForUpdate(¶ms); err != nil {
log.Debugf("CheckForUpdate failed with error: %q", err)
if err == server.ErrNoUpdateAvailable {
log.Debugf("Got query from client %q/%q, no update available.", params.AppVersion, params.OS)
u.closeWithStatus(w, http.StatusNoContent)
return
}
log.Debugf("Got query from client %q/%q: %q.", err)
u.closeWithStatus(w, http.StatusExpectationFailed)
return
}
log.Debugf("Got query from client %q/%q, resolved to upgrade to %q using %q strategy.", params.AppVersion, params.OS, res.Version, res.PatchType)
if res.PatchURL != "" {
res.PatchURL = *flagPublicAddr + res.PatchURL
}
var content []byte
if content, err = json.Marshal(res); err != nil {
u.closeWithStatus(w, http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json")
if _, err := w.Write(content); err != nil {
log.Debugf("Unable to write response: %v", err)
}
return
}
u.closeWithStatus(w, http.StatusNotFound)
return
}
func main() {
// Parsing flags
flag.Parse()
if *flagHelp || *flagPrivateKey == "" {
flag.Usage()
os.Exit(0)
}
server.SetPrivateKey(*flagPrivateKey)
// Creating release manager.
log.Debug("Starting release manager.")
releaseManager = server.NewReleaseManager(*flagGithubOrganization, *flagGithubProject)
// Getting assets...
if err := updateAssets(); err != nil {
// In this case we will not be able to continue.
log.Fatal(err)
}
// Setting a goroutine for pulling updates periodically
go backgroundUpdate()
mux := http.NewServeMux()
mux.Handle("/update", new(updateHandler))
mux.Handle("/patches/", http.StripPrefix("/patches/", http.FileServer(http.Dir(localPatchesDirectory))))
srv := http.Server{
Addr: *flagLocalAddr,
Handler: mux,
}
log.Debugf("Starting up HTTP server at %s.", *flagLocalAddr)
if err := srv.ListenAndServe(); err != nil {
log.Fatalf("ListenAndServe: ", err)
}
}