github.com/stampzilla/stampzilla-go@v2.0.0-rc9+incompatible/nodes/stampzilla-server/servermain/servermain.go (about) 1 package servermain 2 3 import ( 4 "context" 5 "crypto/tls" 6 "crypto/x509" 7 "io/ioutil" 8 "log" 9 "os" 10 "path" 11 "strconv" 12 13 "github.com/olahol/melody" 14 "github.com/onrik/logrus/filename" 15 "github.com/sirupsen/logrus" 16 "github.com/stamp/mdns" 17 "github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/ca" 18 "github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/handlers" 19 "github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/logic" 20 "github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/models" 21 "github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/store" 22 "github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/webserver" 23 "github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/websocket" 24 ) 25 26 // Main contains deps used by server that will be exposed so we can write good end to end tests 27 type Main struct { 28 Config *models.Config 29 Store *store.Store 30 HTTPServer *webserver.Webserver 31 TLSServer *webserver.Webserver 32 CA *ca.CA 33 } 34 35 // New creates a new main 36 func New(config *models.Config) *Main { 37 return &Main{ 38 Config: config, 39 } 40 } 41 42 func (c *Main) Run() { 43 done := c.HTTPServer.Start(":"+c.Config.Port, nil) 44 tlsDone := c.TLSServer.Start(":"+c.Config.TLSPort, c.TLSConfig()) 45 46 // Setup and start mDNS 47 if port, err := strconv.Atoi(c.Config.Port); err == nil { 48 host, _ := os.Hostname() 49 info := []string{"stampzilla-go"} 50 mdnsService, _ := mdns.NewMDNSService(host, "_stampzilla._tcp", "", "", port, nil, info) 51 mdnsServer, _ := mdns.NewServer(&mdns.Config{Zone: mdnsService}) 52 defer mdnsServer.Shutdown() 53 } 54 55 // start logic 56 57 ctx, cancel := context.WithCancel(context.Background()) 58 c.Store.Logic.Start(ctx) 59 c.Store.Scheduler.Start(ctx) 60 61 <-done 62 <-tlsDone 63 cancel() // stop logic 64 c.Store.Logic.Wait() 65 c.Config.Save("config.json") 66 } 67 68 func (m *Main) TLSConfig() *tls.Config { 69 caCert, err := ioutil.ReadFile(path.Join("certificates", "ca.crt")) 70 if err != nil { 71 log.Fatal(err) 72 } 73 caCertPool := x509.NewCertPool() 74 caCertPool.AppendCertsFromPEM(caCert) 75 return &tls.Config{ 76 // Dynamic load certificates 77 GetCertificate: m.CA.GetCertificate, 78 79 // Needed to verify client certificates 80 ClientCAs: caCertPool, 81 //Certificates: []tls.Certificate{*c.CA.TLS}, 82 ClientAuth: tls.VerifyClientCertIfGiven, 83 } 84 } 85 86 // Init initializes the web handlers. Could be used to start server or to test it 87 func (m *Main) Init() { 88 var err error 89 90 filenameHook := filename.NewHook() 91 logrus.AddHook(filenameHook) 92 93 if m.Config.LogLevel != "" { 94 lvl, err := logrus.ParseLevel(m.Config.LogLevel) 95 if err != nil { 96 logrus.Fatal(err) 97 return 98 } 99 logrus.SetLevel(lvl) 100 } 101 102 m.CA, err = ca.LoadOrCreate() 103 if err != nil { 104 logrus.Fatal(err) 105 } 106 107 insecureMelody := melody.New() 108 //TODO i dont like melody anymore.. raw gorilla seems fine? 109 insecureMelody.Config.MaxMessageSize = 0 110 secureMelody := melody.New() 111 //TODO i dont like melody anymore.. raw gorilla seems fine? 112 secureMelody.Config.MaxMessageSize = 0 113 114 insecureSender := websocket.NewWebsocketSender(insecureMelody) 115 secureSender := websocket.NewWebsocketSender(secureMelody) 116 117 sss := logic.NewSavedStateStore() 118 l := logic.New(sss, secureSender) 119 scheduler := logic.NewScheduler(sss, secureSender) 120 m.Store = store.New(l, scheduler, sss) 121 m.CA.SetStore(m.Store) 122 123 if err = m.Store.Load(); err != nil { 124 log.Fatalf("Failed to load state from disk: %s", err) 125 } 126 m.HTTPServer = webserver.New( 127 m.Store, 128 m.Config, 129 handlers.NewInSecureWebsockerHandler(m.Store, m.Config, insecureSender, m.CA), 130 insecureMelody, 131 ) 132 m.TLSServer = webserver.New( 133 m.Store, 134 m.Config, 135 handlers.NewSecureWebsockerHandler(m.Store, m.Config, secureSender, m.CA), 136 secureMelody, 137 ) 138 139 m.Config.Save("config.json") 140 141 m.Store.OnUpdate(handlers.BroadcastUpdate(secureSender)) 142 }