feature: Adds more commands and adds an example.
This commit is contained in:
parent
0d0f16174b
commit
3cb9526716
9 changed files with 352 additions and 41 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,3 +1,8 @@
|
|||
# Go artifacts
|
||||
api/gosrc/sshbackend/sshbackend
|
||||
api/gosrc/dummybackend/dummybackend
|
||||
api/gosrc/externalbackendlauncher/externalbackendlauncher
|
||||
|
||||
# LOM
|
||||
lom/keys
|
||||
|
||||
|
|
154
api/gosrc/backendutil/application.go
Normal file
154
api/gosrc/backendutil/application.go
Normal file
|
@ -0,0 +1,154 @@
|
|||
package backendutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"git.greysoh.dev/imterah/nextnet/commonbackend"
|
||||
"github.com/charmbracelet/log"
|
||||
)
|
||||
|
||||
type BackendApplicationHelper struct {
|
||||
Backend BackendInterface
|
||||
SocketPath string
|
||||
|
||||
socket net.Conn
|
||||
}
|
||||
|
||||
func (helper *BackendApplicationHelper) Start() error {
|
||||
var err error
|
||||
helper.socket, err = net.Dial("unix", helper.SocketPath)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
commandType, commandRaw, err := commonbackend.Unmarshal(helper.socket)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch commandType {
|
||||
case "start":
|
||||
// TODO: implement response logic
|
||||
command, ok := commandRaw.(*commonbackend.StartCommand)
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to typecast")
|
||||
}
|
||||
|
||||
// ok, err :=
|
||||
_, _ = helper.Backend.StartBackend(command.Arguments)
|
||||
case "stop":
|
||||
// TODO: implement response logic
|
||||
_, ok := commandRaw.(*commonbackend.StopCommand)
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to typecast")
|
||||
}
|
||||
|
||||
_, _ = helper.Backend.StopBackend()
|
||||
case "addConnection":
|
||||
// TODO: implement response logic
|
||||
command, ok := commandRaw.(*commonbackend.AddConnectionCommand)
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to typecast")
|
||||
}
|
||||
|
||||
_, _ = helper.Backend.AddConnection(command)
|
||||
case "removeConnection":
|
||||
// TODO: implement response logic
|
||||
command, ok := commandRaw.(*commonbackend.RemoveConnectionCommand)
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to typecast")
|
||||
}
|
||||
|
||||
_, _ = helper.Backend.RemoveConnection(command)
|
||||
case "getAllConnections":
|
||||
_, ok := commandRaw.(*commonbackend.AddConnectionCommand)
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to typecast")
|
||||
}
|
||||
|
||||
connections := helper.Backend.GetAllConnections()
|
||||
|
||||
serverParams := &commonbackend.ConnectionsResponse{
|
||||
Type: "connectionsResponse",
|
||||
Connections: connections,
|
||||
}
|
||||
|
||||
byteData, err := commonbackend.Marshal(serverParams.Type, serverParams)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = helper.socket.Write(byteData); err != nil {
|
||||
return err
|
||||
}
|
||||
case "checkClientParameters":
|
||||
// TODO: implement response logic
|
||||
command, ok := commandRaw.(*commonbackend.CheckClientParameters)
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to typecast")
|
||||
}
|
||||
|
||||
resp := helper.Backend.CheckParametersForConnections(command)
|
||||
resp.Type = "checkParametersResponse"
|
||||
resp.InResponseTo = "checkClientParameters"
|
||||
|
||||
byteData, err := commonbackend.Marshal(resp.Type, resp)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = helper.socket.Write(byteData); err != nil {
|
||||
return err
|
||||
}
|
||||
case "checkServerParameters":
|
||||
// TODO: implement response logic
|
||||
command, ok := commandRaw.(*commonbackend.CheckServerParameters)
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to typecast")
|
||||
}
|
||||
|
||||
resp := helper.Backend.CheckParametersForBackend(command.Arguments)
|
||||
resp.Type = "checkParametersResponse"
|
||||
resp.InResponseTo = "checkServerParameters"
|
||||
|
||||
byteData, err := commonbackend.Marshal(resp.Type, resp)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = helper.socket.Write(byteData); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewHelper(backend BackendInterface) *BackendApplicationHelper {
|
||||
socketPath, ok := os.LookupEnv("NEXTNET_API_SOCK")
|
||||
|
||||
if !ok {
|
||||
log.Warn("NEXTNET_API_SOCK is not defined! This will cause an issue unless the backend manually overwrites it")
|
||||
}
|
||||
|
||||
helper := &BackendApplicationHelper{
|
||||
Backend: backend,
|
||||
SocketPath: socketPath,
|
||||
}
|
||||
|
||||
return helper
|
||||
}
|
|
@ -3,7 +3,7 @@ package backendutil
|
|||
import "git.greysoh.dev/imterah/nextnet/commonbackend"
|
||||
|
||||
type BackendInterface interface {
|
||||
StartBackend() (bool, error)
|
||||
StartBackend(arguments []byte) (bool, error)
|
||||
StopBackend() (bool, error)
|
||||
AddConnection(command *commonbackend.AddConnectionCommand) (bool, error)
|
||||
RemoveConnection(command *commonbackend.RemoveConnectionCommand) (bool, error)
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
package commonbackend
|
||||
|
||||
// Not all of these structs are implemented commands.
|
||||
// Currently unimplemented commands:
|
||||
// GetAllConnectionsRequest
|
||||
// BackendStatusResponse
|
||||
// BackendStatusRequest
|
||||
// ProxyStatusRequest
|
||||
// ProxyStatusResponse
|
||||
// GetAllConnectionsRequest
|
||||
|
||||
// TODO (imterah): Rename AddConnectionCommand/RemoveConnectionCommand to AddProxyCommand/RemoveProxyCommand
|
||||
// and their associated function calls
|
||||
|
||||
type StartCommand struct {
|
||||
Type string // Will be 'start' always
|
||||
Arguments []byte
|
||||
|
@ -25,6 +37,51 @@ type RemoveConnectionCommand struct {
|
|||
Protocol string // Will be either 'tcp' or 'udp'
|
||||
}
|
||||
|
||||
type GetProxyStatus struct {
|
||||
Type string // Will be 'getProxyStatus' always
|
||||
SourceIP string
|
||||
SourcePort uint16
|
||||
DestPort uint16
|
||||
Protocol string // Will be either 'tcp' or 'udp'
|
||||
}
|
||||
|
||||
type ProxyStatusResponse struct {
|
||||
Type string // Will be 'proxyStatusResponse' always
|
||||
SourceIP string
|
||||
SourcePort uint16
|
||||
DestPort uint16
|
||||
Protocol string // Will be either 'tcp' or 'udp'
|
||||
IsActive bool
|
||||
}
|
||||
|
||||
type ProxyConnection struct {
|
||||
SourceIP string
|
||||
SourcePort uint16
|
||||
DestPort uint16
|
||||
Protocol string // Will be either 'tcp' or 'udp'
|
||||
}
|
||||
|
||||
type ProxyConnectionResponse struct {
|
||||
Type string // Will be 'proxyConnectionResponse' always
|
||||
Connections []*ProxyConnection // List of connections
|
||||
}
|
||||
|
||||
type BackendStatusResponse struct {
|
||||
Type string // Will be 'backendStatusResponse' always
|
||||
InResponseTo string // Can be either for 'start' or 'stop'
|
||||
StatusCode int // Either the 'Success' or 'Failure' constant
|
||||
Message string // String message from the client (ex. failed to dial TCP)
|
||||
}
|
||||
|
||||
type BackendStatusRequest struct {
|
||||
Type string // Will be 'backendStatusRequest' always
|
||||
ForProperty string // Can be either for 'start' or 'stop'
|
||||
}
|
||||
|
||||
type GetAllConnectionsRequest struct {
|
||||
Type string // Will be 'getAllConnectionsRequest' always
|
||||
}
|
||||
|
||||
type ClientConnection struct {
|
||||
SourceIP string
|
||||
SourcePort uint16
|
||||
|
@ -33,8 +90,8 @@ type ClientConnection struct {
|
|||
ClientPort uint16
|
||||
}
|
||||
|
||||
type GetAllConnections struct {
|
||||
Type string // Will be 'getAllConnections' always
|
||||
type ConnectionsResponse struct {
|
||||
Type string // Will be 'connectionsResponse' always
|
||||
Connections []*ClientConnection // List of connections
|
||||
}
|
||||
|
||||
|
@ -54,7 +111,7 @@ type CheckServerParameters struct {
|
|||
// Sent as a response to either CheckClientParameters or CheckBackendParameters
|
||||
type CheckParametersResponse struct {
|
||||
Type string // Will be 'checkParametersResponse' always
|
||||
InReplyTo string // Will be either 'checkClientParameters' or 'checkServerParameters'
|
||||
InResponseTo string // Will be either 'checkClientParameters' or 'checkServerParameters'
|
||||
IsValid bool // If true, valid, and if false, invalid
|
||||
Message string // String message from the client (ex. failed to unmarshal JSON: x is not defined)
|
||||
}
|
||||
|
@ -74,10 +131,19 @@ const (
|
|||
const (
|
||||
TCP = iota
|
||||
UDP
|
||||
)
|
||||
|
||||
const (
|
||||
StatusSuccess = iota
|
||||
StatusFailure
|
||||
)
|
||||
|
||||
const (
|
||||
// IP versions
|
||||
IPv4 = 4
|
||||
IPv6 = 6
|
||||
|
||||
// TODO: net has these constants defined already. We should switch to these
|
||||
IPv4Size = 4
|
||||
IPv6Size = 16
|
||||
)
|
||||
|
|
|
@ -156,8 +156,8 @@ func Marshal(commandType string, command interface{}) ([]byte, error) {
|
|||
removeConnectionBytes[6+len(ipBytes)] = protocol
|
||||
|
||||
return removeConnectionBytes, nil
|
||||
case "getAllConnections":
|
||||
allConnectionsCommand, ok := command.(*GetAllConnections)
|
||||
case "connectionsResponse":
|
||||
allConnectionsCommand, ok := command.(*ConnectionsResponse)
|
||||
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to typecast")
|
||||
|
@ -247,9 +247,9 @@ func Marshal(commandType string, command interface{}) ([]byte, error) {
|
|||
|
||||
var checkMethod uint8
|
||||
|
||||
if checkParametersCommand.InReplyTo == "checkClientParameters" {
|
||||
if checkParametersCommand.InResponseTo == "checkClientParameters" {
|
||||
checkMethod = CheckClientParametersID
|
||||
} else if checkParametersCommand.InReplyTo == "checkServerParameters" {
|
||||
} else if checkParametersCommand.InResponseTo == "checkServerParameters" {
|
||||
checkMethod = CheckServerParametersID
|
||||
} else {
|
||||
return nil, fmt.Errorf("invalid mode recieved (must be either checkClientParameters or checkServerParameters)")
|
||||
|
|
|
@ -219,8 +219,8 @@ func TestRemoveConnectionCommandMarshalSupport(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetAllConnectionsCommandMarshalSupport(t *testing.T) {
|
||||
commandInput := &GetAllConnections{
|
||||
Type: "getAllConnections",
|
||||
commandInput := &ConnectionsResponse{
|
||||
Type: "connectionsResponse",
|
||||
Connections: []*ClientConnection{
|
||||
{
|
||||
SourceIP: "127.0.0.1",
|
||||
|
@ -268,7 +268,7 @@ func TestGetAllConnectionsCommandMarshalSupport(t *testing.T) {
|
|||
log.Print("command type does not match up!")
|
||||
}
|
||||
|
||||
commandUnmarshalled, ok := commandUnmarshalledRaw.(*GetAllConnections)
|
||||
commandUnmarshalled, ok := commandUnmarshalledRaw.(*ConnectionsResponse)
|
||||
|
||||
if !ok {
|
||||
t.Fatal("failed typecast")
|
||||
|
@ -419,7 +419,7 @@ func TestCheckServerParametersMarshalSupport(t *testing.T) {
|
|||
func TestCheckParametersResponseMarshalSupport(t *testing.T) {
|
||||
commandInput := &CheckParametersResponse{
|
||||
Type: "checkParametersResponse",
|
||||
InReplyTo: "checkClientParameters",
|
||||
InResponseTo: "checkClientParameters",
|
||||
IsValid: true,
|
||||
Message: "Hello from automated testing",
|
||||
}
|
||||
|
@ -457,9 +457,9 @@ func TestCheckParametersResponseMarshalSupport(t *testing.T) {
|
|||
log.Printf("Types are not equal (orig: %s, unmsh: %s)", commandInput.Type, commandUnmarshalled.Type)
|
||||
}
|
||||
|
||||
if commandInput.InReplyTo != commandUnmarshalled.InReplyTo {
|
||||
if commandInput.InResponseTo != commandUnmarshalled.InResponseTo {
|
||||
t.Fail()
|
||||
log.Printf("InReplyTo's are not equal (orig: %s, unmsh: %s)", commandInput.InReplyTo, commandUnmarshalled.InReplyTo)
|
||||
log.Printf("InResponseTo's are not equal (orig: %s, unmsh: %s)", commandInput.InResponseTo, commandUnmarshalled.InResponseTo)
|
||||
}
|
||||
|
||||
if commandInput.IsValid != commandUnmarshalled.IsValid {
|
||||
|
|
|
@ -254,8 +254,8 @@ func Unmarshal(conn io.Reader) (string, interface{}, error) {
|
|||
}
|
||||
}
|
||||
|
||||
return "getAllConnections", &GetAllConnections{
|
||||
Type: "getAllConnections",
|
||||
return "connectionsResponse", &ConnectionsResponse{
|
||||
Type: "connectionsResponse",
|
||||
Connections: connections,
|
||||
}, errorReturn
|
||||
case CheckClientParametersID:
|
||||
|
@ -377,7 +377,7 @@ func Unmarshal(conn io.Reader) (string, interface{}, error) {
|
|||
|
||||
return "checkParametersResponse", &CheckParametersResponse{
|
||||
Type: "checkParametersResponse",
|
||||
InReplyTo: checkMethod,
|
||||
InResponseTo: checkMethod,
|
||||
IsValid: isValid[0] == 1,
|
||||
Message: message,
|
||||
}, nil
|
||||
|
|
83
api/gosrc/dummybackend/main.go
Normal file
83
api/gosrc/dummybackend/main.go
Normal file
|
@ -0,0 +1,83 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"git.greysoh.dev/imterah/nextnet/backendutil"
|
||||
"git.greysoh.dev/imterah/nextnet/commonbackend"
|
||||
"github.com/charmbracelet/log"
|
||||
)
|
||||
|
||||
type DummyBackend struct {
|
||||
}
|
||||
|
||||
func (backend *DummyBackend) StartBackend(byte []byte) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (backend *DummyBackend) StopBackend() (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (backend *DummyBackend) AddConnection(command *commonbackend.AddConnectionCommand) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (backend *DummyBackend) RemoveConnection(command *commonbackend.RemoveConnectionCommand) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (backend *DummyBackend) GetAllConnections() []*commonbackend.ClientConnection {
|
||||
return []*commonbackend.ClientConnection{}
|
||||
}
|
||||
|
||||
func (backend *DummyBackend) CheckParametersForConnections(clientParameters *commonbackend.CheckClientParameters) *commonbackend.CheckParametersResponse {
|
||||
// You don't have to specify Type and InReplyTo. Those will be handled for you.
|
||||
// Message is optional.
|
||||
return &commonbackend.CheckParametersResponse{
|
||||
IsValid: true,
|
||||
Message: "Valid!",
|
||||
}
|
||||
}
|
||||
|
||||
func (backend *DummyBackend) CheckParametersForBackend(arguments []byte) *commonbackend.CheckParametersResponse {
|
||||
// You don't have to specify Type and InReplyTo. Those will be handled for you.
|
||||
// Message is optional.
|
||||
return &commonbackend.CheckParametersResponse{
|
||||
IsValid: true,
|
||||
Message: "Valid!",
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// When using logging, you should use charmbracelet/log, because that's what everything else uses in this ecosystem of a project. - imterah
|
||||
logLevel := os.Getenv("NEXTNET_LOG_LEVEL")
|
||||
|
||||
if logLevel != "" {
|
||||
switch logLevel {
|
||||
case "debug":
|
||||
log.SetLevel(log.DebugLevel)
|
||||
|
||||
case "info":
|
||||
log.SetLevel(log.InfoLevel)
|
||||
|
||||
case "warn":
|
||||
log.SetLevel(log.WarnLevel)
|
||||
|
||||
case "error":
|
||||
log.SetLevel(log.ErrorLevel)
|
||||
|
||||
case "fatal":
|
||||
log.SetLevel(log.FatalLevel)
|
||||
}
|
||||
}
|
||||
|
||||
backend := &DummyBackend{}
|
||||
|
||||
application := backendutil.NewHelper(backend)
|
||||
err := application.Start()
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("failed execution in application: %s", err.Error())
|
||||
}
|
||||
}
|
|
@ -33,7 +33,10 @@ func main() {
|
|||
tempDir, err := os.MkdirTemp("", "nextnet-sockets-")
|
||||
logLevel := os.Getenv("NEXTNET_LOG_LEVEL")
|
||||
|
||||
if logLevel != "" {
|
||||
if logLevel == "" {
|
||||
logLevel = "fatal"
|
||||
}
|
||||
|
||||
switch logLevel {
|
||||
case "debug":
|
||||
log.SetLevel(log.DebugLevel)
|
||||
|
@ -50,7 +53,6 @@ func main() {
|
|||
case "fatal":
|
||||
log.SetLevel(log.FatalLevel)
|
||||
}
|
||||
}
|
||||
|
||||
if len(os.Args) != 3 {
|
||||
log.Fatalf("missing arguments! example: ./externalbackendlauncher <backend executable> <file with backend arguments>")
|
||||
|
@ -109,8 +111,9 @@ func main() {
|
|||
for {
|
||||
log.Info("starting process...")
|
||||
// TODO: can we reuse cmd?
|
||||
|
||||
cmd := exec.Command(executablePath)
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintf("NEXTNET_API_SOCK=%s", sockPath))
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintf("NEXTNET_API_SOCK=%s", sockPath), fmt.Sprintf("NEXTNET_LOG_LEVEL=%s", logLevel))
|
||||
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = stderr
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue