diff --git a/host/lux_state.go b/host/lux_state.go index dcbfb45..d7b5c74 100644 --- a/host/lux_state.go +++ b/host/lux_state.go @@ -1,6 +1,10 @@ package host -import "lux/proto" +import ( + "encoding/base64" + "lux/proto" + "lux/rpc" +) type LuxState struct { Hostname string @@ -48,3 +52,33 @@ func (state *LuxState) Write(wd *proto.LuxBuffer) { WriteLuxOption(wd, opt) } } + +// RPC + +func (state *LuxState) IntoRpc() rpc.LuxRpcState { + rpcState := rpc.LuxRpcState{ + Options: make([]rpc.LuxRpcOption, 0), + } + + for optType, opt := range state.Options { + switch optType { + case LuxOptionTypeWAN: + wan := opt.(*LuxOptionWAN) + rpcState.WAN = rpc.LuxRpcWAN{ + Addr4: wan.Addr4.String(), + Addr6: wan.Addr4.String(), + } + default: + // encode option in base64 blob + wd := proto.NewLuxBuffer() + opt.Write(&wd) + + rpcState.Options = append(rpcState.Options, rpc.LuxRpcOption{ + Type: int(optType), + Blob: base64.StdEncoding.EncodeToString(wd.AllBytes()), + }) + } + } + + return rpcState +} diff --git a/node/lux_node.go b/node/lux_node.go index 18500bb..e086f29 100644 --- a/node/lux_node.go +++ b/node/lux_node.go @@ -260,12 +260,11 @@ func (node *LuxNode) Register(sv *rpc.LuxRpcServer) { func (node *LuxNode) Handle(request rpc.LuxRpcRequest, rpcType rpc.LuxRpcType) (rpc.LuxRpcResponse, rpc.LuxRpcError, bool) { var rpcRes rpc.LuxRpcResponse - // only root can add hosts or neighbors - if rpcType != rpc.LuxRpcTypeRoot { - return rpcRes, rpc.LUX_RPC_ERROR_ACCESS_DENIED, false - } - if request.Command == "new-host" { + if rpcType != rpc.LuxRpcTypeRoot { + return rpcRes, rpc.LUX_RPC_ERROR_ACCESS_DENIED, false + } + ks := node.router.GetKeyStore() // generate host key, add it to our keystore host, err := crypto.NewLuxKey(proto.LuxTypeHost) @@ -284,6 +283,10 @@ func (node *LuxNode) Handle(request rpc.LuxRpcRequest, rpcType rpc.LuxRpcType) ( Keystore: crypto.LuxKeyStoreIntoRpc(&ksHost), }, rpc.LuxRpcError{}, true } else if request.Command == "new-node" { + if rpcType != rpc.LuxRpcTypeRoot { + return rpcRes, rpc.LUX_RPC_ERROR_ACCESS_DENIED, false + } + // to bootstrap neighbor node, first on this node we generate // and add new node key, then copy all keys with new key to neighbor's keystore ks := node.router.GetKeyStore() @@ -300,6 +303,54 @@ func (node *LuxNode) Handle(request rpc.LuxRpcRequest, rpcType rpc.LuxRpcType) ( return rpc.LuxRpcResponse{ Keystore: crypto.LuxKeyStoreIntoRpc(ks), }, rpc.LuxRpcError{}, true + } else if request.Command == "query" { + // now we get host states either by ID or hostname + node.stateLock.RLock() + defer node.stateLock.RUnlock() + + foundHosts := make([]rpc.LuxRpcHost, 0) + + for _, queryHost := range request.Hosts { + var hostState *LuxHostState + + if queryHost.HostID != "" { + // find by id + hostId, err := proto.ParseLuxID(queryHost.HostID) + if err != nil { + return rpcRes, rpc.LuxRpcGenericError(err), false + } + + var ok bool + hostState, ok = node.state.hosts[hostId] + if !ok { + return rpcRes, rpc.LuxRpcGenericError(err), false + } + } else if queryHost.Hostname != "" { + // find by hostname + found := false + for _, item := range node.state.hosts { + if item.State.Hostname == queryHost.Hostname { + hostState = item + + found = true + break + } + } + + if !found { + return rpcRes, rpc.LUX_RPC_ERROR_HOST_NOT_FOUND, false + } + } + + // serialize host state into xml + foundHosts = append(foundHosts, rpc.LuxRpcHost{ + HostID: hostState.HostId.String(), + Hostname: hostState.State.Hostname, + State: hostState.State.IntoRpc(), + }) + } + + return rpc.LuxRpcResponse{Hosts: foundHosts}, rpc.LuxRpcError{}, true } return rpcRes, rpc.LUX_RPC_ERROR_UNKNOWN_COMMAND, false diff --git a/rpc/lux_rpc_data.go b/rpc/lux_rpc_data.go index 110137d..fed00b3 100644 --- a/rpc/lux_rpc_data.go +++ b/rpc/lux_rpc_data.go @@ -23,10 +23,10 @@ type LuxRpcState struct { } type LuxRpcHost struct { - XMLName xml.Name `xml:"host"` - HostID string `xml:"id,attr"` - Hostname string `xml:"hostname,attr"` - StateBlob string `xml:"state"` + XMLName xml.Name `xml:"host"` + HostID string `xml:"id,attr"` + Hostname string `xml:"hostname,attr"` + State LuxRpcState `xml:"state"` } type LuxRpcRequest struct { diff --git a/rpc/lux_rpc_errors.go b/rpc/lux_rpc_errors.go index d87290d..c494620 100644 --- a/rpc/lux_rpc_errors.go +++ b/rpc/lux_rpc_errors.go @@ -23,6 +23,11 @@ var LUX_RPC_ERROR_GENERIC = LuxRpcError{ Message: "generic error", } +var LUX_RPC_ERROR_HOST_NOT_FOUND = LuxRpcError{ + ErrorCode: 5, + Message: "host not found", +} + func LuxRpcGenericError(err error) LuxRpcError { return LuxRpcError{ ErrorCode: LUX_RPC_ERROR_GENERIC.ErrorCode,