|
|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
- * Copyright (c) 2014, Psiphon Inc.
|
|
|
+ * Copyright (c) 2015, Psiphon Inc.
|
|
|
* All rights reserved.
|
|
|
*
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
@@ -33,14 +33,21 @@ import (
|
|
|
|
|
|
func main() {
|
|
|
|
|
|
+ // Define command-line parameters
|
|
|
+
|
|
|
var configFilename string
|
|
|
flag.StringVar(&configFilename, "config", "", "configuration input file")
|
|
|
|
|
|
+ var embeddedServerEntryListFilename string
|
|
|
+ flag.StringVar(&embeddedServerEntryListFilename, "serverList", "", "embedded server entry list input file")
|
|
|
+
|
|
|
var profileFilename string
|
|
|
flag.StringVar(&profileFilename, "profile", "", "CPU profile output file")
|
|
|
|
|
|
flag.Parse()
|
|
|
|
|
|
+ // Handle required config file parameter
|
|
|
+
|
|
|
if configFilename == "" {
|
|
|
log.Fatalf("configuration file is required")
|
|
|
}
|
|
|
@@ -53,6 +60,8 @@ func main() {
|
|
|
log.Fatalf("error processing configuration file: %s", err)
|
|
|
}
|
|
|
|
|
|
+ // Handle optional profiling parameter
|
|
|
+
|
|
|
if profileFilename != "" {
|
|
|
profileFile, err := os.Create(profileFilename)
|
|
|
if err != nil {
|
|
|
@@ -62,11 +71,37 @@ func main() {
|
|
|
defer pprof.StopCPUProfile()
|
|
|
}
|
|
|
|
|
|
+ // Initialize data store
|
|
|
+
|
|
|
err = psiphon.InitDataStore(config)
|
|
|
if err != nil {
|
|
|
log.Fatalf("error initializing datastore: %s", err)
|
|
|
}
|
|
|
|
|
|
+ // Handle optional embedded server list file parameter
|
|
|
+ // If specified, the embedded server list is loaded and stored before
|
|
|
+ // running Psiphon.
|
|
|
+
|
|
|
+ if embeddedServerEntryListFilename != "" {
|
|
|
+ serverEntryList, err := ioutil.ReadFile(embeddedServerEntryListFilename)
|
|
|
+ if err != nil {
|
|
|
+ log.Fatalf("error loading embedded server entry list file: %s", err)
|
|
|
+ }
|
|
|
+ // TODO: stream embedded server list data? also, the cast makaes an unnecessary copy of a large buffer?
|
|
|
+ serverEntries, err := psiphon.DecodeServerEntryList(string(serverEntryList))
|
|
|
+ if err != nil {
|
|
|
+ log.Fatalf("error decoding embedded server entry list file: %s", err)
|
|
|
+ }
|
|
|
+ // Since embedded server list entries may become stale, they will not
|
|
|
+ // overwrite existing stored entries for the same server.
|
|
|
+ err = psiphon.StoreServerEntries(serverEntries, false)
|
|
|
+ if err != nil {
|
|
|
+ log.Fatalf("error storing embedded server entry list data: %s", err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Set logfile, if configured
|
|
|
+
|
|
|
if config.LogFilename != "" {
|
|
|
logFile, err := os.OpenFile(config.LogFilename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
|
|
|
if err != nil {
|
|
|
@@ -76,6 +111,8 @@ func main() {
|
|
|
log.SetOutput(logFile)
|
|
|
}
|
|
|
|
|
|
+ // Run Psiphon
|
|
|
+
|
|
|
controller := psiphon.NewController(config)
|
|
|
shutdownBroadcast := make(chan struct{})
|
|
|
controllerWaitGroup := new(sync.WaitGroup)
|
|
|
@@ -85,6 +122,8 @@ func main() {
|
|
|
controller.Run(shutdownBroadcast)
|
|
|
}()
|
|
|
|
|
|
+ // Wait for an OS signal, then stop Psiphon and exit
|
|
|
+
|
|
|
systemStopSignal := make(chan os.Signal, 1)
|
|
|
signal.Notify(systemStopSignal, os.Interrupt, os.Kill)
|
|
|
<-systemStopSignal
|