Skip to content

Commit 0b960f5

Browse files
committed
Squashed 'src/github.com/getlantern/autoupdate-server/' changes from b2de4c4..2422360
2422360 Copying changes from flashlight. 3f8eeab Merge pull request #1 from bzz/fix-semver-api 60f3fca Backport Semver v.3.0.0 API changes 5df6f4c Keeping up to date with flashlight-build. git-subtree-dir: src/github.com/getlantern/autoupdate-server git-subtree-split: 242236072e9be212c1c6a9325c864564b6a00729
1 parent 7aa69a7 commit 0b960f5

File tree

14 files changed

+235
-300
lines changed

14 files changed

+235
-300
lines changed

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
all:
2+
GOOS=linux GOARCH=amd64 go build -o autoupdate-server
3+
4+
clean:
5+
rm -f autoupdate-server

README.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,18 @@ the client can use to patch itself.
1212

1313
## Requisites
1414

15+
Make sure you have the [bsdiff](http://www.daemonology.net/bsdiff/) program
16+
installed:
17+
18+
```
19+
apt-get instal -y bsdiff
20+
yum install -y bsdiff
21+
brew install bsdiff
22+
```
23+
24+
The `bsdiff` program is used to calculate a binary diff of two files and
25+
generate a patch.
26+
1527
In order to sign binary files you'll need a keypair:
1628

1729
```sh
@@ -25,7 +37,7 @@ configuration.
2537
## How to run the autoupdate server
2638

2739
```
28-
PRIVATE_KEY=private.pem ./autoupdate-server
40+
./autoupdate-server -k private.pem
2941
```
3042

3143
## Just testing?
@@ -62,10 +74,11 @@ BL0RSJZb4JgqCtRleQRcQg94+b4gvEllScprTHSQnIbrUVof79FoVQ==
6274
-----END RSA PRIVATE KEY-----
6375
```
6476

65-
Save it to `private.pem` and run the server:
77+
Save it to `private.pem` and run the server pointing to the autoupdate-server
78+
repo that belongs to the getlantern organization:
6679

6780
```sh
68-
PRIVATE_KEY=private.pem go run *.go
81+
go run *.go -k private.pem -o getlantern -n autoupdate-server
6982
# 2015/03/13 18:22:41 Starting release manager.
7083
# 2015/03/13 18:22:41 Updating assets...
7184
```

config.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@ import (
55
)
66

77
const (
8-
listenAddr = ":9197"
9-
githubNamespace = "getlantern"
10-
githubRepo = "autoupdate-server"
11-
githubRefreshTime = time.Minute * 30
12-
publicAddr = "http://127.0.0.1:9197/"
13-
patchesDirectory = "./patches/"
8+
githubRefreshTime = time.Minute * 30
9+
localPatchesDirectory = "./patches/"
1410
)

main.go

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,35 @@ package main
22

33
import (
44
"encoding/json"
5-
"github.com/getlantern/autoupdate-server/server"
6-
"log"
5+
"flag"
76
"net/http"
7+
"os"
88
"time"
9+
10+
"github.com/getlantern/autoupdate-server/server"
11+
"github.com/getlantern/golog"
12+
)
13+
14+
var (
15+
flagPrivateKey = flag.String("k", "", "Path to private key.")
16+
flagLocalAddr = flag.String("l", ":6868", "Local bind address.")
17+
flagPublicAddr = flag.String("p", "http://127.0.0.1:6868/", "Public address.")
18+
flagGithubOrganization = flag.String("o", "getlantern", "Github organization.")
19+
flagGithubProject = flag.String("n", "lantern", "Github project name.")
20+
flagHelp = flag.Bool("h", false, "Shows help.")
921
)
1022

11-
var releaseManager *server.ReleaseManager
23+
var (
24+
log = golog.LoggerFor("autoupdate-server")
25+
releaseManager *server.ReleaseManager
26+
)
1227

1328
type updateHandler struct {
1429
}
1530

1631
// updateAssets checks for new assets released on the github releases page.
1732
func updateAssets() error {
18-
log.Printf("Updating assets...")
33+
log.Debug("Updating assets...")
1934
if err := releaseManager.UpdateAssetsMap(); err != nil {
2035
return err
2136
}
@@ -28,24 +43,11 @@ func backgroundUpdate() {
2843
time.Sleep(githubRefreshTime)
2944
// Updating assets...
3045
if err := updateAssets(); err != nil {
31-
log.Printf("updateAssets: %s", err)
46+
log.Debugf("updateAssets: %s", err)
3247
}
3348
}
3449
}
3550

36-
func init() {
37-
// Creating release manager.
38-
log.Printf("Starting release manager.")
39-
releaseManager = server.NewReleaseManager(githubNamespace, githubRepo)
40-
// Getting assets...
41-
if err := updateAssets(); err != nil {
42-
// In this case we will not be able to continue.
43-
log.Fatal(err)
44-
}
45-
// Setting a goroutine for pulling updates periodically
46-
go backgroundUpdate()
47-
}
48-
4951
func (u *updateHandler) closeWithStatus(w http.ResponseWriter, status int) {
5052
w.WriteHeader(status)
5153
w.Write([]byte(http.StatusText(status)))
@@ -67,16 +69,17 @@ func (u *updateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
6769
}
6870

6971
if res, err = releaseManager.CheckForUpdate(&params); err != nil {
70-
log.Printf("releaseManager.CheckForUpdate failed with error: %q", err)
72+
log.Debugf("CheckForUpdate failed with error: %q", err)
7173
if err == server.ErrNoUpdateAvailable {
7274
u.closeWithStatus(w, http.StatusNoContent)
75+
return
7376
}
7477
u.closeWithStatus(w, http.StatusExpectationFailed)
7578
return
7679
}
7780

7881
if res.PatchURL != "" {
79-
res.PatchURL = publicAddr + res.PatchURL
82+
res.PatchURL = *flagPublicAddr + res.PatchURL
8083
}
8184

8285
var content []byte
@@ -97,20 +100,42 @@ func (u *updateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
97100

98101
func main() {
99102

103+
// Parsing flags
104+
flag.Parse()
105+
106+
if *flagHelp || *flagPrivateKey == "" {
107+
flag.Usage()
108+
os.Exit(0)
109+
}
110+
111+
server.SetPrivateKey(*flagPrivateKey)
112+
113+
// Creating release manager.
114+
log.Debug("Starting release manager.")
115+
releaseManager = server.NewReleaseManager(*flagGithubOrganization, *flagGithubProject)
116+
// Getting assets...
117+
if err := updateAssets(); err != nil {
118+
// In this case we will not be able to continue.
119+
log.Fatal(err)
120+
}
121+
122+
// Setting a goroutine for pulling updates periodically
123+
go backgroundUpdate()
124+
100125
mux := http.NewServeMux()
101126

102127
mux.Handle("/update", new(updateHandler))
103-
mux.Handle("/patches/", http.StripPrefix("/patches/", http.FileServer(http.Dir(patchesDirectory))))
128+
mux.Handle("/patches/", http.StripPrefix("/patches/", http.FileServer(http.Dir(localPatchesDirectory))))
104129

105130
srv := http.Server{
106-
Addr: listenAddr,
131+
Addr: *flagLocalAddr,
107132
Handler: mux,
108133
}
109134

110-
log.Printf("Starting up HTTP server at %s.", listenAddr)
135+
log.Debugf("Starting up HTTP server at %s.", *flagLocalAddr)
111136

112137
if err := srv.ListenAndServe(); err != nil {
113-
log.Fatal("ListenAndServe: ", err)
138+
log.Fatalf("ListenAndServe: ", err)
114139
}
115140

116141
}

server/asset.go

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package server
22

33
import (
4-
"crypto/sha1"
4+
"compress/bzip2"
5+
"crypto/sha256"
56
"fmt"
67
"io"
78
"log"
89
"net/http"
910
"os"
11+
"path"
1012
)
1113

1214
const (
@@ -16,16 +18,28 @@ const (
1618
func init() {
1719
err := os.MkdirAll(assetsDirectory, os.ModeDir|0700)
1820
if err != nil {
19-
log.Fatal("Could not create directory for storing assets: %q", err)
21+
log.Fatalf("Could not create directory for storing assets: %q", err)
2022
}
2123
}
2224

2325
// downloadAsset grabs the contents of the body of the given URL and stores
24-
// then into $ASSETS_DIRECTORY/SHA1($URL).
26+
// then into $ASSETS_DIRECTORY/$BASENAME.SHA256_SUM($URL)
2527
func downloadAsset(uri string) (localfile string, err error) {
26-
localfile = assetsDirectory + fmt.Sprintf("%x", sha1.Sum([]byte(uri)))
28+
basename := path.Base(uri)
29+
fileExt := path.Ext(basename)
30+
31+
// We'll be appending 65 chars to create a local file name for the asset,
32+
// this 60-char limit prevents creating a file name longer than 255 chars. We
33+
// could allow a few more characters until 255 but 60 sounds like a sane
34+
// limit.
35+
if len(basename) > 60 {
36+
basename = basename[:60]
37+
}
38+
39+
localfile = assetsDirectory + fmt.Sprintf("%s.%x", basename, sha256.Sum256([]byte(uri)))
2740

2841
if !fileExists(localfile) {
42+
var body io.Reader
2943
var res *http.Response
3044

3145
if res, err = http.Get(uri); err != nil {
@@ -36,6 +50,8 @@ func downloadAsset(uri string) (localfile string, err error) {
3650
return "", fmt.Errorf("Expecting 200 OK, got: %s", res.Status)
3751
}
3852

53+
defer res.Body.Close()
54+
3955
var fp *os.File
4056

4157
if fp, err = os.Create(localfile); err != nil {
@@ -44,15 +60,17 @@ func downloadAsset(uri string) (localfile string, err error) {
4460

4561
defer fp.Close()
4662

47-
if _, err = io.Copy(fp, res.Body); err != nil {
63+
if fileExt == ".bz2" {
64+
body = bzip2.NewReader(res.Body)
65+
} else {
66+
body = res.Body
67+
}
68+
69+
if _, err = io.Copy(fp, body); err != nil {
4870
return "", err
4971
}
5072

5173
}
5274

5375
return localfile, nil
5476
}
55-
56-
func assetURL(localfile string) (url string) {
57-
return localfile
58-
}

server/asset_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
)
77

88
const (
9-
testAssetURL = `https://github.com/getlantern/autoupdate-server/releases/download/v0.4/autoupdate-binary-darwin-x86.v4`
9+
testAssetURL = `https://github.com/getlantern/autoupdate/releases/download/2.0.0-beta3/update_darwin_amd64`
1010
)
1111

1212
func TestDownloadAsset(t *testing.T) {

server/bindiff.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ import (
77
"log"
88
"os"
99
"os/exec"
10+
"sync"
11+
)
12+
13+
var (
14+
generatePatchMu sync.Mutex
1015
)
1116

1217
// Patch struct is a representation of a patch generated by bsdiff.
@@ -23,7 +28,7 @@ const (
2328
func init() {
2429
err := os.MkdirAll(patchesDirectory, os.ModeDir|0700)
2530
if err != nil {
26-
log.Fatal("Could not create directory for storing patches: %q", err)
31+
log.Fatalf("Could not create directory for storing patches: %q", err)
2732
}
2833
}
2934

@@ -41,12 +46,12 @@ func fileHash(s string) string {
4146
h := sha256.New()
4247

4348
if fp, err = os.Open(s); err != nil {
44-
log.Fatal("Failed to open file %s: %q", s, err)
49+
log.Fatalf("Failed to open file %s: %q", s, err)
4550
}
4651
defer fp.Close()
4752

4853
if _, err = io.Copy(h, fp); err != nil {
49-
log.Fatal("Failed to read file %s: %q", s, err)
54+
log.Fatalf("Failed to read file %s: %q", s, err)
5055
}
5156

5257
return fmt.Sprintf("%x", h.Sum(nil))
@@ -76,6 +81,7 @@ func bspatch(oldfile string, newfile string, patchfile string) (err error) {
7681
}
7782

7883
func bsdiff(oldfile string, newfile string) (patchfile string, err error) {
84+
7985
if !fileExists(oldfile) {
8086
return "", fmt.Errorf("File %s does not exist.", oldfile)
8187
}
@@ -87,7 +93,7 @@ func bsdiff(oldfile string, newfile string) (patchfile string, err error) {
8793
oldfileHash := fileHash(oldfile)
8894
newfileHash := fileHash(newfile)
8995

90-
patchfile = patchesDirectory + fmt.Sprintf("%x", sha256.Sum256([]byte(oldfileHash+newfileHash))) + ".patch"
96+
patchfile = patchesDirectory + fmt.Sprintf("%x", sha256.Sum256([]byte(oldfileHash+"|"+newfileHash)))
9197

9298
if fileExists(patchfile) {
9399
// Patch already exists, no need to compute it again.
@@ -108,8 +114,11 @@ func bsdiff(oldfile string, newfile string) (patchfile string, err error) {
108114
return patchfile, nil
109115
}
110116

111-
// GeneratePatch compares the contents of two URLs and generates a patch.
112-
func GeneratePatch(oldfileURL string, newfileURL string) (p *Patch, err error) {
117+
// generatePatch compares the contents of two URLs and generates a patch.
118+
func generatePatch(oldfileURL string, newfileURL string) (p *Patch, err error) {
119+
generatePatchMu.Lock()
120+
defer generatePatchMu.Unlock()
121+
113122
p = new(Patch)
114123

115124
if p.oldfile, err = downloadAsset(oldfileURL); err != nil {

server/bindiff_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,25 @@ func writeFile(file string, content []byte) (err error) {
2727
func TestBinaryDiff(t *testing.T) {
2828
var err error
2929
// Creating some files for testing.
30-
if err = writeFile("_tests/file_a", []byte(`in a gadda da vida, honey, don't you know that I'm loving you.`)); err != nil {
30+
if err = writeFile("_tests/file-a", []byte(`in a gadda da vida, honey, don't you know that I'm loving you.`)); err != nil {
3131
t.Fatal(fmt.Sprintf("Failed to write test file: %q", err))
3232
}
33-
if err = writeFile("_tests/file_b", []byte(`in a gadda da vida, baby, don't you know that I'll always be true.`)); err != nil {
33+
if err = writeFile("_tests/file-b", []byte(`in a gadda da vida, baby, don't you know that I'll always be true.`)); err != nil {
3434
t.Fatal(fmt.Sprintf("Failed to write test file: %q", err))
3535
}
3636
// Creating binary diffs.
3737
var patchfile string
38-
if patchfile, err = bsdiff("_tests/file_a", "_tests/file_b"); err != nil {
38+
if patchfile, err = bsdiff("_tests/file-a", "_tests/file-b"); err != nil {
3939
t.Fatal(fmt.Sprintf("Failed to generate binary diff: %q", err))
4040
}
4141
// Testing patch application.
42-
if err = bspatch("_tests/file_a", "_tests/file_c", patchfile); err != nil {
42+
if err = bspatch("_tests/file-a", "_tests/file-c", patchfile); err != nil {
4343
t.Fatal(fmt.Sprintf("Failed to apply binary diff: %q", err))
4444
}
45-
// At this point a new _tests/file_c should have been generated by patching
46-
// _tests/file_a with the patch created before, the contents of this file_c
47-
// must be exactly the same than the contents of file_b.
48-
if fileHash("_tests/file_c") != fileHash("_tests/file_b") {
45+
// At this point a new _tests/file-c should have been generated by patching
46+
// _tests/file-a with the patch created before, the contents of this file-c
47+
// must be exactly the same than the contents of file-b.
48+
if fileHash("_tests/file-c") != fileHash("_tests/file-b") {
4949
t.Fatal("File hashes after patch must be equal.")
5050
}
5151
}

0 commit comments

Comments
 (0)