diff --git a/app/apps.go b/app/apps.go index 83210d5..f9e9089 100644 --- a/app/apps.go +++ b/app/apps.go @@ -1,6 +1,7 @@ package app import ( + "database/sql" "fmt" "net" "net/http" @@ -12,12 +13,13 @@ type ( RunningApps map[string][]string Applications struct { - running RunningApps - nextPN int // Next available port number + running RunningApps + nextPN int // Next available port number + defaultDB *sql.DB } IApplications interface { - RegisterApps() // Retrieve all applications and serve + ServeApps() // Retrieve all applications and serve GetRunningApps() RunningApps // Get all running applications GetAppServers(string) []string // Get all servers' address that an application runs on ConnectToServer(string) (net.Conn, error) // Connect to an application running locally @@ -25,15 +27,16 @@ type ( } ) -func InitApplications() IApplications { +func InitApplications(defaultDB *sql.DB) IApplications { return &Applications{ - running: RunningApps{}, - nextPN: 12000, // New servers will listen on port number :12000 and above + running: RunningApps{}, + nextPN: 12000, // New servers will listen on port number :12000 and above for static apps + defaultDB: defaultDB, } } // Retrieve all applications and serve -func (a *Applications) RegisterApps() { +func (a *Applications) ServeApps() { // Serve the welcome page welcomePort := a.ServeStatic("./assets/welcome/") // We'll view the welcome page on the default port :80 diff --git a/app/cli/apps.go b/app/cli/apps.go index 488a2b5..b34f7f1 100644 --- a/app/cli/apps.go +++ b/app/cli/apps.go @@ -1,21 +1,95 @@ package cli import ( + "database/sql" "log" "os" + "strings" + "time" "github.com/DeeStarks/conoid/utils" + "github.com/aquasecurity/table" + _ "github.com/mattn/go-sqlite3" ) -type AppCommand struct{} +type AppCommand struct { + defaultDB *sql.DB +} func (cmd *CLICommands) Apps() *AppCommand { - return &AppCommand{} + return &AppCommand{ + defaultDB: cmd.defaultDB, + } +} + +type AppProcess struct { + Pid string + Name string + Status string + Type string + Listeners []string + RootDirectory string + ClientAddress string + Tunnelled bool + CreatedAt int64 } // List running applications func (ac *AppCommand) ListRunning() { - log.Println("Running processes") + rows, err := ac.defaultDB.Query(` + SELECT + pid, name, status, type, listeners, + root_directory, client_address, tunnelled, created_at + FROM processes WHERE status="running" + `) + if err != nil { + log.Println("Error retrieving running apps:", err) + return + } + + // Parse result + var processes []AppProcess + for rows.Next() { + var process AppProcess + var listeners string + + err = rows.Scan( + &process.Pid, &process.Name, &process.Status, &process.Type, + &listeners, &process.RootDirectory, &process.ClientAddress, + &process.Tunnelled, &process.CreatedAt, + ) + if err != nil { + log.Println("Error retrieving running apps:", err) + return + } + + // Listeners are stored in the db a string separated by comma + // we'll split that into slice + process.Listeners = strings.Split(listeners, ",") + // Append the process to list of processes + processes = append(processes, process) + } + + // Draw table to list processes + t := table.New(os.Stdout) + t.SetDividers(table.UnicodeRoundedDividers) + + t.SetHeaders("PID", "NAME", "TYPE", "LISTENERS", "ROOT", "CLIENT", "TUNNELLED", "CREATED") + for _, p := range processes { + created_at := utils.TimeAgo(p.CreatedAt, time.Now().Unix()) + listeners := strings.Join(p.Listeners, ", ") + tunnelled := "False" + if p.Tunnelled { + tunnelled = "True" + } + + t.AddRow( + string(p.Pid), p.Name, p.Type, listeners, p.RootDirectory, + p.ClientAddress, tunnelled, created_at, + ) + } + t.Render() + } // List all applications diff --git a/app/cli/cli.go b/app/cli/cli.go index 70f657a..01591b1 100644 --- a/app/cli/cli.go +++ b/app/cli/cli.go @@ -1,12 +1,29 @@ package cli +import ( + "database/sql" + "log" + + "github.com/DeeStarks/conoid/config" + _ "github.com/mattn/go-sqlite3" +) + type ICLICommands interface { Apps() *AppCommand } -type CLICommands struct{} +type CLICommands struct { + defaultDB *sql.DB +} // Accept and process CLI commands. func NewCLICommands() ICLICommands { - return &CLICommands{} + // Connect to the default db + defaultDB, err := sql.Open("sqlite3", config.DEFAULT_DB) + if err != nil { + log.Panicln("Could not connect DB:", err) + } + return &CLICommands{ + defaultDB: defaultDB, + } } diff --git a/app/server.go b/app/server.go index 0929bbc..a6796d9 100644 --- a/app/server.go +++ b/app/server.go @@ -1,6 +1,7 @@ package app import ( + "database/sql" "fmt" "io" "log" @@ -8,18 +9,28 @@ import ( "github.com/DeeStarks/conoid/app/tools" "github.com/DeeStarks/conoid/config" + _ "github.com/mattn/go-sqlite3" ) type Server struct { - apps IApplications + apps IApplications + defaultDB *sql.DB } func NewServer() *Server { - apps := InitApplications() // initialize applications - apps.RegisterApps() // Register all apps + // Connect to the default db + defaultDB, err := sql.Open("sqlite3", config.DEFAULT_DB) + if err != nil { + log.Panicln("Could not connect DB:", err) + } + + // initialize and start running applications + apps := InitApplications(defaultDB) + apps.ServeApps() return &Server{ - apps: apps, + apps: apps, + defaultDB: defaultDB, } } diff --git a/app/tools/loadbalancer.go b/app/tools/loadbalancer.go index 9cf3eb3..b83bb32 100644 --- a/app/tools/loadbalancer.go +++ b/app/tools/loadbalancer.go @@ -5,14 +5,14 @@ type ILoadBalancer interface { } type LoadBalancer struct { - srvs []string // Servers to balaance load across - roundRobin int + srvs []string // Servers to balaance load across + roundRobin int } // Creates a new instance of load balancer func NewLoadBalancer(srvs []string) ILoadBalancer { return &LoadBalancer{ - srvs: srvs, + srvs: srvs, roundRobin: 0, } } diff --git a/app/tools/loadbalancer_test.go b/app/tools/loadbalancer_test.go index 41c3566..c62e3ca 100644 --- a/app/tools/loadbalancer_test.go +++ b/app/tools/loadbalancer_test.go @@ -8,9 +8,9 @@ import ( func TestLoadBalancer(t *testing.T) { var servers = []string{"google.com", "localhost", "stackoverflow.com", "yahoo.com"} - var tests = []struct{ + var tests = []struct { expected string - } { + }{ { expected: "google.com", }, @@ -38,4 +38,4 @@ func TestLoadBalancer(t *testing.T) { t.Errorf("Expected %s; Got %s", tc.expected, server) } } -} \ No newline at end of file +} diff --git a/go.mod b/go.mod index a54cfb8..c20dc33 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,17 @@ module github.com/DeeStarks/conoid go 1.17 require ( + github.com/aquasecurity/table v1.7.2 + github.com/mattn/go-sqlite3 v1.14.14 github.com/spf13/cobra v1.5.0 gopkg.in/yaml.v3 v3.0.1 ) require ( github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/rivo/uniseg v0.2.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect + golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect ) diff --git a/go.sum b/go.sum index 3a25d71..eea7868 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,35 @@ +github.com/aquasecurity/table v1.7.2 h1:mextUtadM4WdDRtwmUVYPKaDSRCDDSvTam+aPMQg9eE= +github.com/aquasecurity/table v1.7.2/go.mod h1:eqOmvjjB7AhXFgFqpJUEE/ietg7RrMSJZXyTN8E/wZw= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw= +github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c h1:aFV+BgZ4svzjfabn8ERpuB4JI4N6/rdy1iusx77G3oU= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 h1:CBpWXWQpIRjzmkkA+M7q9Fqnwd2mZr3AFqexg8YTfoM= +golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=