1
0
Fork 0
forked from External/grumble
grumble/grumble.go

169 lines
3.8 KiB
Go

// Copyright (c) 2010 The Grumble Authors
// The use of this source code is goverened by a BSD-style
// license that can be found in the LICENSE-file.
package main
import (
"flag"
"fmt"
"grumble/blobstore"
"log"
"net"
"os"
"path/filepath"
"regexp"
"rpc"
"runtime"
)
func defaultGrumbleDir() string {
dirname := ".grumble"
if runtime.GOOS == "windows" {
dirname = "grumble"
}
return filepath.Join(os.Getenv("HOME"), dirname)
}
func defaultDataDir() string {
return filepath.Join(defaultGrumbleDir(), "data")
}
func defaultBlobDir() string {
return filepath.Join(defaultGrumbleDir(), "blob")
}
func defaultCtlNet() string {
if runtime.GOOS == "windows" {
return "tcp"
}
return "unix"
}
func defaultCtlAddr() string {
if runtime.GOOS == "windows" {
return "localhost:5454"
}
return filepath.Join(defaultGrumbleDir(), ".ctl")
}
var help *bool = flag.Bool("help", false, "Show this help")
var datadir *string = flag.String("datadir", defaultDataDir(), "Directory to use for server storage")
var blobdir *string = flag.String("blobdir", defaultBlobDir(), "Directory to use for blob storage")
var ctlnet *string = flag.String("ctlnet", defaultCtlNet(), "Network to use for ctl socket")
var ctladdr *string = flag.String("ctladdr", defaultCtlAddr(), "Address to use for ctl socket")
var gencert *bool = flag.Bool("gencert", false, "Generate a self-signed certificate for use with Grumble")
var servers map[int64]*Server
func Usage() {
fmt.Fprintf(os.Stderr, "usage: grumble [options]\n")
fmt.Fprintf(os.Stderr, "remote control: grumble [options] ctl [ctlopts]\n")
flag.PrintDefaults()
}
func main() {
var err os.Error
flag.Parse()
if *help == true {
Usage()
return
}
for i, str := range os.Args {
if str == "ctl" {
GrumbleCtl(os.Args[i+1:])
return
}
}
log.SetPrefix("[G] ")
log.SetFlags(log.LstdFlags|log.Lmicroseconds)
log.Printf("Grumble")
log.Printf("Using blob directory: %s", *blobdir)
err = blobstore.Open(*blobdir, true)
if err != nil {
log.Fatalf("Unable to initialize blobstore: %v", err.String())
}
// Generate a cert?
if *gencert {
certfn := filepath.Join(*datadir, "cert")
keyfn := filepath.Join(*datadir, "key")
log.Printf("Generating 2048-bit RSA keypair for self-signed certificate...")
err := GenerateSelfSignedCert(certfn, keyfn)
if err != nil {
log.Printf("Error: %v", err)
return
}
log.Printf("Certificate output to %v", certfn)
log.Printf("Private key output to %v", keyfn)
log.Printf("Done generating certificate and private key.")
log.Printf("Please restart Grumble to make use of the generated certificate and private key.")
return
}
f, err := os.Open(*datadir)
if err != nil {
log.Fatalf("Murmur import failed: %s", err.String())
}
defer f.Close()
names, err := f.Readdirnames(-1)
if err != nil {
log.Fatalf("Murmur import failed: %s", err.String())
}
servers = make(map[int64]*Server)
for _, name := range names {
if matched, _ := regexp.MatchString("^[0-9]+$", name); matched {
log.Printf("Loading server %v", name)
s, err := NewServerFromFrozen(name)
if err != nil {
log.Fatalf("Unable to load server: %v", err)
}
err = s.FreezeToFile()
if err != nil {
log.Fatalf("Unable to freeze server to disk: %v", err)
}
servers[s.Id] = s
go s.ListenAndMurmur()
}
}
if len(servers) == 0 {
s, err := NewServer(1, "0.0.0.0", 64738)
if err != nil {
log.Fatalf("Couldn't start server: %s", err.String())
}
servers[s.Id] = s
os.Mkdir(filepath.Join(*datadir, fmt.Sprintf("%v", 1)), 0750)
s.FreezeToFile()
go s.ListenAndMurmur()
}
if *ctlnet == "unix" {
os.Remove(*ctladdr)
}
lis, err := net.Listen(*ctlnet, *ctladdr)
if err != nil {
log.Panicf("Unable to listen on ctl socket: %v", err)
}
ctl := &ControlRPC{}
rpc.RegisterName("ctl", ctl)
go rpc.Accept(lis)
if len(servers) > 0 {
go SignalHandler()
select {}
}
}