forked from hiproz/minicdn
/
main.go
138 lines (117 loc) · 3.28 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
package main
import (
"fmt"
"log"
"net/http"
"net/url"
"os"
"os/signal"
"syscall"
"github.com/alecthomas/kingpin"
)
var (
VERSION = "0.1"
wslog *log.Logger
mOpts MasterOptions
sOpts SlaveOptions
)
type MasterOptions struct {
LogFile string
MirrorAddr *url.URL
CacheDir string
ListenAddr string
Secret string
}
type SlaveOptions struct {
Secret string
CacheDir string
ListenAddr string
MasterAddr *url.URL
}
func init() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
}
func InitSignal() {
sig := make(chan os.Signal, 10)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
go func() {
for {
s := <-sig
fmt.Println("Got signal:", s)
if state.IsClosed() {
fmt.Println("Cold close !!!")
os.Exit(1)
}
fmt.Println("Warm close, waiting ...")
go func() {
state.Close()
os.Exit(0)
}()
}
}()
}
func checkErr(er error) {
if er != nil {
log.Fatal(er)
}
}
func runMaster(opts MasterOptions) {
logfile := opts.LogFile
if logfile == "-" || logfile == "" {
wslog = log.New(os.Stderr, "", log.LstdFlags)
} else {
fd, err := os.OpenFile(logfile, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
if err != nil {
log.Fatal(err)
}
wslog = log.New(fd, "", 0)
}
http.HandleFunc(defaultWSURL, NewWsHandler(opts.MirrorAddr.String(), wslog))
http.HandleFunc("/", NewFileHandler(true, opts.MirrorAddr.String(), opts.CacheDir))
http.HandleFunc("/_log", func(w http.ResponseWriter, r *http.Request) {
if logfile == "" || logfile == "-" {
http.Error(w, "Log file not found", 404)
return
}
http.ServeFile(w, r, logfile)
})
log.Printf("Listening on %s", opts.ListenAddr)
InitSignal()
log.Fatal(http.ListenAndServe(opts.ListenAddr, nil))
}
func runSlave(opts SlaveOptions) {
if err := InitPeer(opts.MasterAddr.String(), opts.ListenAddr, opts.CacheDir, opts.Secret); err != nil {
log.Fatal(err)
}
log.Printf("Listening on %s", opts.ListenAddr)
InitSignal()
log.Fatal(http.ListenAndServe(opts.ListenAddr, nil))
}
func main() {
app := kingpin.New("minicdn", "Master node which manage slaves")
app.Flag("cachedir", "Cache file directory").Short('d').Default("cache").ExistingDirVar(&mOpts.CacheDir) //.StringVar(&mOpts.CacheDir)
app.Flag("secret", "Secret key for server").Short('s').Default("sandy mandy").StringVar(&mOpts.Secret)
ma := app.Command("master", "CDN Master")
ma.Flag("addr", "Listen address").Default(":7010").StringVar(&mOpts.ListenAddr)
ma.Flag("log", "Log file, - for stdout").Short('l').Default("-").StringVar(&mOpts.LogFile)
ma.Flag("mirror", "Mirror http address, ex: http://t.co/").Required().URLVar(&mOpts.MirrorAddr)
sa := app.Command("slave", "Slave node")
sa.Flag("addr", "Listen address").Default(":7020").StringVar(&sOpts.ListenAddr)
sa.Flag("maddr", "Master server address, ex: localhost:7010").Short('m').Required().URLVar(&sOpts.MasterAddr)
app.Version(VERSION).Author("codeskyblue")
app.HelpFlag.Short('h')
app.VersionFlag.Short('v')
kingpin.CommandLine.Help = "The very simple and mini CDN"
// parse command line
cmdName := kingpin.MustParse(app.Parse(os.Args[1:]))
sOpts.CacheDir = mOpts.CacheDir
sOpts.Secret = mOpts.Secret
switch cmdName {
case ma.FullCommand():
runMaster(mOpts)
case sa.FullCommand():
runSlave(sOpts)
default:
log.Fatalf("Unknown command: %s", cmdName)
}
}