forked from cwtch.im/cwtch
Merge branch 'server-config' of dan/cwtch into master
This commit is contained in:
commit
0cfd672c83
|
@ -5,13 +5,11 @@ import (
|
|||
"crypto/rsa"
|
||||
"cwtch.im/cwtch/protocol"
|
||||
"encoding/asn1"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/s-rah/go-ricochet/utils"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -292,19 +290,3 @@ func (p *Profile) EncryptMessageToGroup(message string, groupID string) ([]byte,
|
|||
}
|
||||
return nil, errors.New("group does not exist")
|
||||
}
|
||||
|
||||
// Save makes a opy of the profile in the given file
|
||||
func (p *Profile) Save(profilefile string) error {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
bytes, _ := json.Marshal(p)
|
||||
return ioutil.WriteFile(profilefile, bytes, 0600)
|
||||
}
|
||||
|
||||
// LoadProfile loads a saved profile from a file.
|
||||
func LoadProfile(profilefile string) (*Profile, error) {
|
||||
bytes, _ := ioutil.ReadFile(profilefile)
|
||||
profile := new(Profile)
|
||||
err := json.Unmarshal(bytes, &profile)
|
||||
return profile, err
|
||||
}
|
||||
|
|
|
@ -6,18 +6,6 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func TestProfile(t *testing.T) {
|
||||
profile := GenerateNewProfile("Sarah")
|
||||
err := profile.Save("./profile_test")
|
||||
if err != nil {
|
||||
t.Errorf("Should have saved profile, but got error: %v", err)
|
||||
}
|
||||
loadedProfile, err := LoadProfile("./profile_test")
|
||||
if err != nil || loadedProfile.Name != "Sarah" {
|
||||
t.Errorf("Issue loading profile from file %v %v", err, loadedProfile)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProfileIdentity(t *testing.T) {
|
||||
sarah := GenerateNewProfile("Sarah")
|
||||
alice := GenerateNewProfile("Alice")
|
||||
|
|
|
@ -62,7 +62,7 @@ func NewCwtchPeer(name string) *CwtchPeer {
|
|||
// Save saves the CwtchPeer profile state to a file.
|
||||
func (cp *CwtchPeer) Save(profilefile string) error {
|
||||
cp.mutex.Lock()
|
||||
bytes, _ := json.Marshal(cp)
|
||||
bytes, _ := json.MarshalIndent(cp, "", "\t")
|
||||
err := ioutil.WriteFile(profilefile, bytes, 0600)
|
||||
cp.profilefile = profilefile
|
||||
cp.mutex.Unlock()
|
||||
|
|
|
@ -2,35 +2,33 @@ package main
|
|||
|
||||
import (
|
||||
cwtchserver "cwtch.im/cwtch/server"
|
||||
"github.com/s-rah/go-ricochet/utils"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
const privateKeyFile = "./private_key"
|
||||
const (
|
||||
serverConfigFile = "serverConfig.json"
|
||||
)
|
||||
|
||||
func checkAndGenPrivateKey(privateKeyFile string) {
|
||||
if _, err := os.Stat(privateKeyFile); os.IsNotExist(err) {
|
||||
log.Printf("no private key found!")
|
||||
log.Printf("generating new private key...")
|
||||
pk, err := utils.GeneratePrivateKey()
|
||||
func confirmOrCopySampleConfig() {
|
||||
// if no config file, attempt to copy sample
|
||||
if _, err := os.Stat(serverConfigFile); os.IsNotExist(err) {
|
||||
raw, err := ioutil.ReadFile(serverConfigFile + ".sample")
|
||||
if err != nil {
|
||||
log.Fatalf("error generating new private key: %v\n", err)
|
||||
}
|
||||
err = ioutil.WriteFile(privateKeyFile, []byte(utils.PrivateKeyToString(pk)), 0400)
|
||||
if err != nil {
|
||||
log.Fatalf("error writing new private key to file %s: %v\n", privateKeyFile, err)
|
||||
log.Fatal("Could not read sample config to copy: ", err)
|
||||
}
|
||||
ioutil.WriteFile(serverConfigFile, raw, 0600)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
checkAndGenPrivateKey(privateKeyFile)
|
||||
confirmOrCopySampleConfig()
|
||||
serverConfig := cwtchserver.LoadConfig(serverConfigFile)
|
||||
|
||||
server := new(cwtchserver.Server)
|
||||
log.Printf("starting cwtch server...")
|
||||
|
||||
// TODO load params from .cwtch/server.conf or command line flag
|
||||
server.Run(privateKeyFile, 100000)
|
||||
server.Run(serverConfig)
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"maxBufferLines": 100000
|
||||
serverReporting: {
|
||||
reportingGroupId: ""
|
||||
reportingServerAddr: ""
|
||||
}
|
||||
}
|
|
@ -7,27 +7,22 @@ import (
|
|||
"cwtch.im/cwtch/storage"
|
||||
"github.com/s-rah/go-ricochet/application"
|
||||
"github.com/s-rah/go-ricochet/channels"
|
||||
"github.com/s-rah/go-ricochet/utils"
|
||||
"log"
|
||||
)
|
||||
|
||||
// Server encapsulates a complete, compliant Cwtch server.
|
||||
type Server struct {
|
||||
app *application.RicochetApplication
|
||||
config *Config
|
||||
}
|
||||
|
||||
// Run starts a server with the given privateKey
|
||||
// TODO: surface errors
|
||||
func (s *Server) Run(privateKeyFile string, bufferSize int) {
|
||||
func (s *Server) Run(serverConfig *Config) {
|
||||
s.config = serverConfig
|
||||
cwtchserver := new(application.RicochetApplication)
|
||||
|
||||
pk, err := utils.LoadPrivateKeyFromFile(privateKeyFile)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("error reading private key file: %v", err)
|
||||
}
|
||||
|
||||
l, err := application.SetupOnion("127.0.0.1:9051", "tcp4", "", pk, 9878)
|
||||
l, err := application.SetupOnion("127.0.0.1:9051", "tcp4", "", s.config.PrivateKey(), 9878)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("error setting up onion service: %v", err)
|
||||
|
@ -36,7 +31,7 @@ func (s *Server) Run(privateKeyFile string, bufferSize int) {
|
|||
af := application.ApplicationInstanceFactory{}
|
||||
af.Init()
|
||||
ms := new(storage.MessageStore)
|
||||
ms.Init("cwtch.messages", bufferSize)
|
||||
ms.Init("cwtch.messages", s.config.MaxBufferLines)
|
||||
af.AddHandler("im.cwtch.server.listen", func(rai *application.ApplicationInstance) func() channels.Handler {
|
||||
si := new(Instance)
|
||||
si.Init(rai, cwtchserver, ms)
|
||||
|
@ -66,10 +61,10 @@ func (s *Server) Run(privateKeyFile string, bufferSize int) {
|
|||
}
|
||||
})
|
||||
|
||||
cwtchserver.Init("cwtch server for "+l.Addr().String()[0:16], pk, af, new(application.AcceptAllContactManager))
|
||||
cwtchserver.Init("cwtch server for "+l.Addr().String()[0:16], s.config.PrivateKey(), af, new(application.AcceptAllContactManager))
|
||||
log.Printf("cwtch server running on cwtch:%s", l.Addr().String()[0:16])
|
||||
s.app = cwtchserver
|
||||
cwtchserver.Run(l)
|
||||
s.app.Run(l)
|
||||
}
|
||||
|
||||
// Shutdown kills the app closing all connections and freeing all goroutines
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"github.com/s-rah/go-ricochet/utils"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"encoding/json"
|
||||
"crypto/rsa"
|
||||
)
|
||||
|
||||
// Reporting is a struct for storing a the config a server needs to be a peer, and connect to a group to report
|
||||
type Reporting struct {
|
||||
PeerPrivateKey string `json:"privateKey"`
|
||||
ReportingGroupID string `json:"reportingGroupId"`
|
||||
ReportingServerAddr string `json:"reportingServerAddr"`
|
||||
}
|
||||
|
||||
// Config is a struct for storing basic server configuration
|
||||
type Config struct {
|
||||
MaxBufferLines int `json:"maxBufferLines"`
|
||||
PrivateKeyBytes string `json:"privateKey"`
|
||||
ServerReporting Reporting `json:"serverReporting"`
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
// PrivateKey returns an rsa.PrivateKey generated from the config's PrivateKeyBytes
|
||||
func (config *Config) PrivateKey() *rsa.PrivateKey {
|
||||
pk, err := utils.ParsePrivateKey([]byte(config.PrivateKeyBytes))
|
||||
if err != nil {
|
||||
log.Println("Error parsing private key: ", err)
|
||||
}
|
||||
return pk
|
||||
}
|
||||
|
||||
// Save dumps the latest version of the config to a json file given by filename
|
||||
func (config *Config) Save(filename string) {
|
||||
config.lock.Lock()
|
||||
defer config.lock.Unlock()
|
||||
bytes, _ := json.MarshalIndent(config, "", "\t")
|
||||
ioutil.WriteFile(filename, bytes, 0600)
|
||||
}
|
||||
|
||||
// LoadConfig loads a Config from a json file specified by filename
|
||||
func LoadConfig(filename string) *Config {
|
||||
raw, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
log.Fatal("Could not read config: ", err)
|
||||
}
|
||||
|
||||
config := Config{}
|
||||
err = json.Unmarshal(raw, &config)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal("Error reading config: ", err)
|
||||
}
|
||||
|
||||
if config.PrivateKeyBytes == "" {
|
||||
config.generatePrivateKey()
|
||||
config.Save(filename)
|
||||
}
|
||||
if config.ServerReporting.PeerPrivateKey == "" {
|
||||
config.generatePeerPrivateKey()
|
||||
config.Save(filename)
|
||||
}
|
||||
|
||||
return &config
|
||||
}
|
||||
|
||||
func (config *Config) generatePrivateKey() {
|
||||
pk, err := utils.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
log.Fatalf("error generating new private key: %v\n", err)
|
||||
}
|
||||
config.lock.Lock()
|
||||
config.PrivateKeyBytes = utils.PrivateKeyToString(pk)
|
||||
config.lock.Unlock()
|
||||
}
|
||||
|
||||
func (config *Config) generatePeerPrivateKey() {
|
||||
pk, err := utils.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
log.Fatalf("error generating new peer private key: %v\n", err)
|
||||
}
|
||||
config.lock.Lock()
|
||||
config.ServerReporting.PeerPrivateKey = utils.PrivateKeyToString(pk)
|
||||
config.lock.Unlock()
|
||||
}
|
|
@ -129,7 +129,8 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
|||
serverAddr, _ = utils.GetOnionAddress(serverKey)
|
||||
server = new(cwtchserver.Server)
|
||||
fmt.Println("Starting cwtch server...")
|
||||
go server.Run(localKeyfile, 100)
|
||||
config := cwtchserver.Config{ PrivateKeyBytes: utils.PrivateKeyToString(serverKey), MaxBufferLines: 100, ServerReporting: cwtchserver.Reporting{ } }
|
||||
go server.Run(&config)
|
||||
|
||||
// let tor get established
|
||||
fmt.Printf("Establishing Tor hidden service: %v...\n", serverAddr)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
#!/bin/sh
|
||||
|
||||
echo "Checking code quality (you want to see no output here)"
|
||||
echo ""
|
||||
|
||||
echo "Vetting:"
|
||||
go list ./... | xargs go vet
|
||||
|
||||
echo ""
|
||||
echo "Linting:"
|
||||
|
||||
go list ./... | xargs golint
|
|
@ -18,4 +18,3 @@ go test ${1} -coverprofile=server.cover.out -v ./server
|
|||
echo "mode: set" > coverage.out && cat *.cover.out | grep -v mode: | sort -r | \
|
||||
awk '{if($1 != last) {print $0;last=$1}}' >> coverage.out
|
||||
rm -rf *.cover.out
|
||||
go list ./... | xargs go vet
|
||||
|
|
Loading…
Reference in New Issue