mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-03 08:28:31 +00:00
Combine config objects, improve first-run ux
This commit is contained in:
parent
a6508d32ab
commit
4eee83a561
5 changed files with 104 additions and 98 deletions
|
@ -2,56 +2,52 @@ package main // import "bitbucket.org/stendec/frankerfacez/socketserver/cmd/sock
|
|||
|
||||
import (
|
||||
"../../internal/server"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
var origin *string = flag.String("origin", "localhost:8001", "Client-visible origin of the socket server")
|
||||
var bindAddress *string = flag.String("listen", "", "Address to bind to, if different from origin")
|
||||
var usessl *bool = flag.Bool("ssl", false, "Enable the use of SSL for connecting clients and backend connections")
|
||||
var certificateFile *string = flag.String("crt", "ssl.crt", "CA-signed SSL certificate file")
|
||||
var privateKeyFile *string = flag.String("key", "ssl.key", "SSL private key file")
|
||||
|
||||
var naclKeysFile *string = flag.String("naclkey", "naclkeys.json", "Keypairs for the NaCl crypto library, for communicating with the backend.")
|
||||
var configFilename *string = flag.String("config", "config.json", "Configuration file, including the keypairs for the NaCl crypto library, for communicating with the backend.")
|
||||
var generateKeys *bool = flag.Bool("genkeys", false, "Generate NaCl keys instead of serving requests.\nArguments: [int serverId] [base64 backendPublic]\nThe backend public key can either be specified in base64 on the command line, or put in the json file later.")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
if *generateKeys {
|
||||
GenerateKeys(*naclKeysFile)
|
||||
GenerateKeys(*configFilename)
|
||||
return
|
||||
}
|
||||
|
||||
if *origin == "" {
|
||||
log.Fatalln("--origin argument required")
|
||||
confFile, err := os.Open(*configFilename)
|
||||
if os.IsNotExist(err) {
|
||||
fmt.Println("Error: No config file. Run with -genkeys and edit config.json")
|
||||
os.Exit(3)
|
||||
}
|
||||
if *bindAddress == "" {
|
||||
bindAddress = origin
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if (*certificateFile == "") != (*privateKeyFile == "") {
|
||||
log.Fatalln("Either both --crt and --key can be provided, or neither.")
|
||||
conf := &server.ConfigFile{}
|
||||
confBytes, err := ioutil.ReadAll(confFile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
conf := &server.Config{
|
||||
SSLKeyFile: *privateKeyFile,
|
||||
SSLCertificateFile: *certificateFile,
|
||||
UseSSL: *usessl,
|
||||
NaclKeysFile: *naclKeysFile,
|
||||
|
||||
SocketOrigin: *origin,
|
||||
err = json.Unmarshal(confBytes, &conf)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
httpServer := &http.Server{
|
||||
Addr: *bindAddress,
|
||||
Addr: conf.ListenAddr,
|
||||
}
|
||||
|
||||
server.SetupServerAndHandle(conf, httpServer.TLSConfig, nil)
|
||||
|
||||
var err error
|
||||
if conf.UseSSL {
|
||||
err = httpServer.ListenAndServeTLS(*certificateFile, *privateKeyFile)
|
||||
err = httpServer.ListenAndServeTLS(conf.SSLCertificateFile, conf.SSLKeyFile)
|
||||
} else {
|
||||
err = httpServer.ListenAndServe()
|
||||
}
|
||||
|
@ -63,11 +59,13 @@ func main() {
|
|||
|
||||
func GenerateKeys(outputFile string) {
|
||||
if flag.NArg() < 1 {
|
||||
log.Fatal("The server ID must be specified")
|
||||
fmt.Println("Specify a numeric server ID after -genkeys")
|
||||
os.Exit(2)
|
||||
}
|
||||
if flag.NArg() >= 2 {
|
||||
server.GenerateKeys(outputFile, flag.Arg(0), flag.Arg(1))
|
||||
} else {
|
||||
server.GenerateKeys(outputFile, flag.Arg(0), "")
|
||||
}
|
||||
fmt.Println("Keys generated. Now edit config.json")
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -29,7 +28,7 @@ var serverId int
|
|||
|
||||
var messageBufferPool sync.Pool
|
||||
|
||||
func SetupBackend(config *Config) {
|
||||
func SetupBackend(config *ConfigFile) {
|
||||
backendHttpClient.Timeout = 60 * time.Second
|
||||
backendUrl = config.BackendUrl
|
||||
if responseCache != nil {
|
||||
|
@ -41,21 +40,10 @@ func SetupBackend(config *Config) {
|
|||
|
||||
messageBufferPool.New = New4KByteBuffer
|
||||
|
||||
var keys CryptoKeysBuf
|
||||
file, err := os.Open(config.NaclKeysFile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
dec := json.NewDecoder(file)
|
||||
err = dec.Decode(&keys)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var theirPublic, ourPrivate [32]byte
|
||||
copy(theirPublic[:], keys.TheirPublicKey)
|
||||
copy(ourPrivate[:], keys.OurPrivateKey)
|
||||
serverId = keys.ServerId
|
||||
copy(theirPublic[:], config.BackendPublicKey)
|
||||
copy(ourPrivate[:], config.OurPrivateKey)
|
||||
serverId = config.ServerId
|
||||
|
||||
box.Precompute(&backendSharedKey, &theirPublic, &ourPrivate)
|
||||
}
|
||||
|
@ -193,7 +181,7 @@ func FetchBacklogData(chatSubs []string) ([]ClientMessage, error) {
|
|||
|
||||
func GenerateKeys(outputFile, serverId, theirPublicStr string) {
|
||||
var err error
|
||||
output := CryptoKeysBuf{}
|
||||
output := ConfigFile{}
|
||||
|
||||
output.ServerId, err = strconv.Atoi(serverId)
|
||||
if err != nil {
|
||||
|
@ -212,19 +200,16 @@ func GenerateKeys(outputFile, serverId, theirPublicStr string) {
|
|||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
output.TheirPublicKey = theirPublic
|
||||
output.BackendPublicKey = theirPublic
|
||||
}
|
||||
|
||||
file, err := os.Create(outputFile)
|
||||
fmt.Println(ourPublic, ourPrivate)
|
||||
bytes, err := json.MarshalIndent(output, "", "\t")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
enc := json.NewEncoder(file)
|
||||
err = enc.Encode(output)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = file.Close()
|
||||
fmt.Println(string(bytes))
|
||||
err = ioutil.WriteFile(outputFile, bytes, 0600)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -6,31 +6,16 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"golang.org/x/net/websocket"
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"html/template"
|
||||
)
|
||||
|
||||
const MAX_PACKET_SIZE = 1024
|
||||
|
||||
type Config struct {
|
||||
// SSL/TLS
|
||||
SSLCertificateFile string
|
||||
SSLKeyFile string
|
||||
UseSSL bool
|
||||
|
||||
// NaCl keys for backend messages
|
||||
NaclKeysFile string
|
||||
|
||||
// Hostname of the socket server
|
||||
SocketOrigin string
|
||||
// URL to the backend server
|
||||
BackendUrl string
|
||||
}
|
||||
|
||||
// A command is how the client refers to a function on the server. It's just a string.
|
||||
type Command string
|
||||
|
||||
|
@ -85,10 +70,10 @@ var ExpectedStringAndInt = errors.New("Error: Expected array of string, int as a
|
|||
var ExpectedStringAndBool = errors.New("Error: Expected array of string, bool as arguments.")
|
||||
var ExpectedStringAndIntGotFloat = errors.New("Error: Second argument was a float, expected an integer.")
|
||||
|
||||
var gconfig *Config
|
||||
var gconfig *ConfigFile
|
||||
|
||||
// Create a websocket.Server with the options from the provided Config.
|
||||
func setupServer(config *Config, tlsConfig *tls.Config) *websocket.Server {
|
||||
func setupServer(config *ConfigFile, tlsConfig *tls.Config) *websocket.Server {
|
||||
gconfig = config
|
||||
sockConf, err := websocket.NewConfig("/", config.SocketOrigin)
|
||||
if err != nil {
|
||||
|
@ -120,28 +105,36 @@ func setupServer(config *Config, tlsConfig *tls.Config) *websocket.Server {
|
|||
|
||||
// Set up a websocket listener and register it on /.
|
||||
// (Uses http.DefaultServeMux .)
|
||||
func SetupServerAndHandle(config *Config, tlsConfig *tls.Config, serveMux *http.ServeMux) {
|
||||
func SetupServerAndHandle(config *ConfigFile, tlsConfig *tls.Config, serveMux *http.ServeMux) {
|
||||
sockServer := setupServer(config, tlsConfig)
|
||||
|
||||
if serveMux == nil {
|
||||
serveMux = http.DefaultServeMux
|
||||
}
|
||||
serveMux.HandleFunc("/", ServeWebsocketOrCatbag(sockServer.ServeHTTP))
|
||||
serveMux.Handle("/assets", http.FileServer(nil)) // TODO
|
||||
serveMux.HandleFunc("/pub_msg", HBackendPublishRequest)
|
||||
serveMux.HandleFunc("/dump_backlog", HBackendDumpBacklog)
|
||||
serveMux.HandleFunc("/update_and_pub", HBackendUpdateAndPublish)
|
||||
}
|
||||
|
||||
var Catbag = template.Must(template.New(`
|
||||
var Memes = template.Must(template.New("catbag").Parse(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CatBag</title>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
`).Parse("html"))
|
||||
<link rel="stylesheet" href="//cdn.frankerfacez.com/script/catbag.css">
|
||||
<div id="container">
|
||||
<div id="zf0"></div><div id="zf1"></div><div id="zf2"></div>
|
||||
<div id="zf3"></div><div id="zf4"></div><div id="zf5"></div>
|
||||
<div id="zf6"></div><div id="zf7"></div><div id="zf8"></div>
|
||||
<div id="zf9"></div><div id="catbag"></div>
|
||||
<div id="bottom">
|
||||
A <a href="http://www.frankerfacez.com/">FrankerFaceZ</a> Service
|
||||
— CatBag by <a href="http://www.twitch.tv/wolsk">Wolsk</a>
|
||||
<br>
|
||||
This socket server hosted by {{.}}
|
||||
</div>
|
||||
</div>
|
||||
`))
|
||||
|
||||
func ServeWebsocketOrCatbag(sockfunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -149,8 +142,7 @@ func ServeWebsocketOrCatbag(sockfunc func(http.ResponseWriter, *http.Request)) h
|
|||
sockfunc(w, r)
|
||||
return
|
||||
} else {
|
||||
|
||||
Catbag.Execute(w, nil)
|
||||
Memes.Execute(w, "Todo Add Feature")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,20 +126,36 @@ func TGetUrls(testserver *httptest.Server) TURLs {
|
|||
}
|
||||
}
|
||||
|
||||
const TNaclKeysLocation = "/tmp/test_naclkeys.json"
|
||||
|
||||
func TSetup(testserver **httptest.Server, urls *TURLs) {
|
||||
if backendSharedKey[0] == 0 {
|
||||
GenerateKeys(TNaclKeysLocation, "2", "+ZMqOmxhaVrCV5c0OMZ09QoSGcJHuqQtJrwzRD+JOjE=")
|
||||
}
|
||||
DumpCache()
|
||||
|
||||
conf := &ConfigFile{
|
||||
ServerId: 20,
|
||||
UseSSL: false,
|
||||
SocketOrigin: "localhost:2002",
|
||||
BannerHTML: `
|
||||
<!DOCTYPE html>
|
||||
<title>CatBag</title>
|
||||
<link rel="stylesheet" href="//cdn.frankerfacez.com/script/catbag.css">
|
||||
<div id="container">
|
||||
<div id="zf0"></div><div id="zf1"></div><div id="zf2"></div>
|
||||
<div id="zf3"></div><div id="zf4"></div><div id="zf5"></div>
|
||||
<div id="zf6"></div><div id="zf7"></div><div id="zf8"></div>
|
||||
<div id="zf9"></div><div id="catbag"></div>
|
||||
<div id="bottom">
|
||||
A <a href="http://www.frankerfacez.com/">FrankerFaceZ</a> Service
|
||||
— CatBag by <a href="http://www.twitch.tv/wolsk">Wolsk</a>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
OurPublicKey: []byte{176, 149, 72, 209, 35, 42, 110, 220, 22, 236, 212, 129, 213, 199, 1, 227, 185, 167, 150, 159, 117, 202, 164, 100, 9, 107, 45, 141, 122, 221, 155, 73},
|
||||
OurPrivateKey: []byte{247, 133, 147, 194, 70, 240, 211, 216, 223, 16, 241, 253, 120, 14, 198, 74, 237, 180, 89, 33, 146, 146, 140, 58, 88, 160, 2, 246, 112, 35, 239, 87},
|
||||
BackendPublicKey: []byte{19, 163, 37, 157, 50, 139, 193, 85, 229, 47, 166, 21, 153, 231, 31, 133, 41, 158, 8, 53, 73, 0, 113, 91, 13, 181, 131, 248, 176, 18, 1, 107},
|
||||
}
|
||||
gconfig = conf
|
||||
SetupBackend(conf)
|
||||
|
||||
if testserver != nil {
|
||||
conf := &Config{
|
||||
UseSSL: false,
|
||||
NaclKeysFile: TNaclKeysLocation,
|
||||
SocketOrigin: "localhost:2002",
|
||||
}
|
||||
serveMux := http.NewServeMux()
|
||||
SetupServerAndHandle(conf, nil, serveMux)
|
||||
|
||||
|
|
|
@ -9,24 +9,39 @@ import (
|
|||
|
||||
const CryptoBoxKeyLength = 32
|
||||
|
||||
type CryptoKeysBuf struct {
|
||||
OurPrivateKey []byte
|
||||
OurPublicKey []byte
|
||||
TheirPublicKey []byte
|
||||
ServerId int
|
||||
type ConfigFile struct {
|
||||
// Numeric server id known to the backend
|
||||
ServerId int
|
||||
ListenAddr string
|
||||
// Hostname of the socket server
|
||||
SocketOrigin string
|
||||
// URL to the backend server
|
||||
BackendUrl string
|
||||
// Memes go here
|
||||
BannerHTML string
|
||||
|
||||
// SSL/TLS
|
||||
UseSSL bool
|
||||
SSLCertificateFile string
|
||||
SSLKeyFile string
|
||||
|
||||
// Nacl keys
|
||||
OurPrivateKey []byte
|
||||
OurPublicKey []byte
|
||||
BackendPublicKey []byte
|
||||
}
|
||||
|
||||
type ClientMessage struct {
|
||||
// Message ID. Increments by 1 for each message sent from the client.
|
||||
// When replying to a command, the message ID must be echoed.
|
||||
// When sending a server-initiated message, this is -1.
|
||||
MessageID int `json:_`
|
||||
MessageID int
|
||||
// The command that the client wants from the server.
|
||||
// When sent from the server, the literal string 'True' indicates success.
|
||||
// Before sending, a blank Command will be converted into SuccessCommand.
|
||||
Command Command `json:cmd`
|
||||
Command Command
|
||||
// Result of json.Unmarshal on the third field send from the client
|
||||
Arguments interface{} `json:data`
|
||||
Arguments interface{}
|
||||
|
||||
origArguments string
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue