implement node entry point
This commit is contained in:
parent
0231524afc
commit
10266f26ef
3 changed files with 152 additions and 0 deletions
129
main.go
129
main.go
|
|
@ -5,9 +5,13 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"lux/crypto"
|
"lux/crypto"
|
||||||
|
"lux/node"
|
||||||
"lux/proto"
|
"lux/proto"
|
||||||
|
"lux/rpc"
|
||||||
"os"
|
"os"
|
||||||
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
var isNode bool
|
var isNode bool
|
||||||
|
|
@ -17,6 +21,8 @@ var configPath string
|
||||||
var rpcPath string
|
var rpcPath string
|
||||||
var bootstrap bool
|
var bootstrap bool
|
||||||
var justNodeId bool
|
var justNodeId bool
|
||||||
|
var daemonize bool
|
||||||
|
var pidPath string
|
||||||
|
|
||||||
type NodeConfig struct {
|
type NodeConfig struct {
|
||||||
XMLName xml.Name `xml:"node"`
|
XMLName xml.Name `xml:"node"`
|
||||||
|
|
@ -29,6 +35,8 @@ type NodeConfig struct {
|
||||||
ID string `xml:"id"`
|
ID string `xml:"id"`
|
||||||
Address string `xml:"address"`
|
Address string `xml:"address"`
|
||||||
} `xml:"neighbor"`
|
} `xml:"neighbor"`
|
||||||
|
|
||||||
|
RPCEndpoints []string `xml:"rpc"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func bootstrapNode() {
|
func bootstrapNode() {
|
||||||
|
|
@ -64,6 +72,121 @@ func bootstrapNode() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func nodeMain() {
|
||||||
|
xmlBytes, err := os.ReadFile(configPath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
var config NodeConfig
|
||||||
|
if err := xml.Unmarshal(xmlBytes, &config); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "failed to parse xml: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check presense of keystore and id in config
|
||||||
|
if config.KeyStore == "" {
|
||||||
|
fmt.Fprintln(os.Stderr, "no keystore path specified!")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if config.ID == "" {
|
||||||
|
fmt.Fprintln(os.Stderr, "no ID in config! You need to --bootstrap")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeId, err := proto.ParseLuxID(config.ID)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "failed to parse node id: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// load keystore
|
||||||
|
ks := crypto.NewLuxKeyStore(config.KeyStore)
|
||||||
|
|
||||||
|
nodeKey, ok := ks.Get(nodeId)
|
||||||
|
if !ok {
|
||||||
|
fmt.Fprintln(os.Stderr, "node key is not present in key store!")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create node
|
||||||
|
node := node.NewLuxNode(nodeKey, ks)
|
||||||
|
|
||||||
|
// add interior exterior channels
|
||||||
|
for _, interior := range config.Interior {
|
||||||
|
if err := node.AddInterior(interior); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "failed to add interior %s: %v\n", interior, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, exterior := range config.Exterior {
|
||||||
|
if err := node.AddExterior(exterior); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "failed to add exterior %s: %v\n", exterior, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add neighbors
|
||||||
|
for _, neighbor := range config.Neighbors {
|
||||||
|
neighId, err := proto.ParseLuxID(neighbor.ID)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "failed to parse neigh id %s: %v\n", neighbor.ID, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := node.AddNeighbor(neighId, neighbor.Address); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "failed to add neighbor %s: %v\n", neighbor.ID, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create rpc server
|
||||||
|
sv := rpc.NewLuxRpcServer()
|
||||||
|
// TODO: register node controllers
|
||||||
|
|
||||||
|
// parse and and spawn rpc endpoints
|
||||||
|
for _, rpcPath := range config.RPCEndpoints {
|
||||||
|
if strings.HasPrefix(rpcPath, "unix://") {
|
||||||
|
path := rpcPath[7:]
|
||||||
|
|
||||||
|
if err := sv.AddEndpoint("unix", path, rpc.LuxRpcTypeRoot); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "failed to add root rpc %s: %v\n", path, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(rpcPath, "tcp://") {
|
||||||
|
path := rpcPath[6:]
|
||||||
|
|
||||||
|
if err := sv.AddEndpoint("tcp", path, rpc.LuxRpcTypeQuery); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "failed to add query rpc %s: %v\n", path, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(os.Stderr, "unknown rpc type %s. It must be either unix:// or tcp://\n", rpcPath)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: daemonize
|
||||||
|
|
||||||
|
// register go channel to receive unix signals,
|
||||||
|
// while hogging main thread to read them and take action.
|
||||||
|
// its important to keep main thread alive for process to run
|
||||||
|
sigs := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
|
||||||
|
for {
|
||||||
|
sig := <-sigs
|
||||||
|
switch sig {
|
||||||
|
case syscall.SIGINT:
|
||||||
|
case syscall.SIGTERM:
|
||||||
|
// stop node daemon
|
||||||
|
node.Stop()
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// first, we need to determine who we are: node, host or rpc.
|
// first, we need to determine who we are: node, host or rpc.
|
||||||
// determine by executable name (lux binary will be symlinked to lux-node, lux-host, luc-rpc),
|
// determine by executable name (lux binary will be symlinked to lux-node, lux-host, luc-rpc),
|
||||||
|
|
@ -75,6 +198,8 @@ func main() {
|
||||||
flag.StringVar(&rpcPath, "rpc-path", "", "path to RPC UNIX socket or TCP socket, must be in unix:// or tcp:// form")
|
flag.StringVar(&rpcPath, "rpc-path", "", "path to RPC UNIX socket or TCP socket, must be in unix:// or tcp:// form")
|
||||||
flag.BoolVar(&bootstrap, "bootstrap", false, "bootstrap node keystore. config must be specified")
|
flag.BoolVar(&bootstrap, "bootstrap", false, "bootstrap node keystore. config must be specified")
|
||||||
flag.BoolVar(&justNodeId, "just-node-id", false, "when bootstrapping only output node id to stdout")
|
flag.BoolVar(&justNodeId, "just-node-id", false, "when bootstrapping only output node id to stdout")
|
||||||
|
flag.BoolVar(&daemonize, "daemonize", false, "run LUX as daemon in background")
|
||||||
|
flag.StringVar(&pidPath, "pid", "", "after daemonization LUX will write its PID here")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if !isNode && !isHost && !isRpc {
|
if !isNode && !isHost && !isRpc {
|
||||||
|
|
@ -100,4 +225,8 @@ func main() {
|
||||||
bootstrapNode()
|
bootstrapNode()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if isNode {
|
||||||
|
nodeMain()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,15 @@ func NewLuxID() LuxID {
|
||||||
return LuxID{uuid.New()}
|
return LuxID{uuid.New()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ParseLuxID(idStr string) (LuxID, error) {
|
||||||
|
uuid, err := uuid.Parse(idStr)
|
||||||
|
if err != nil {
|
||||||
|
return LuxID{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return LuxID{uuid}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (id *LuxID) Read(rd *LuxBuffer) error {
|
func (id *LuxID) Read(rd *LuxBuffer) error {
|
||||||
bytes, err := rd.ReadNext(16)
|
bytes, err := rd.ReadNext(16)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
14
rpc/lux_rpc_errors.go
Normal file
14
rpc/lux_rpc_errors.go
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
package rpc
|
||||||
|
|
||||||
|
// all errors are defined here. since RPC is sync locked,
|
||||||
|
// no problem would be mutating RequestID
|
||||||
|
|
||||||
|
var LUX_RPC_ERROR_UNKNOWN_CONTROLLER = LuxRpcError{
|
||||||
|
ErrorCode: 1,
|
||||||
|
Message: "unknown controller",
|
||||||
|
}
|
||||||
|
|
||||||
|
var LUX_RPC_ERROR_ACCESS_DENIED = LuxRpcError{
|
||||||
|
ErrorCode: 2,
|
||||||
|
Message: "access denied",
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue