Skip to content

Commit

Permalink
Skysocks Monitor (#47)
Browse files Browse the repository at this point in the history
* implement skysocks-lite-client

* create dockerfile

* implement skysocks-monitor

* update docker build/push to dockerhub commands for skysocks-monitor

* add dummy skysocks-monitor config on docker configs

* modify Makefile

* fix wrong api path

* update ascii of cli app

* fix typo and name issue on tpd monitor"

* fix errors condition
  • Loading branch information
mrpalide authored Jan 27, 2024
1 parent 34cb3f3 commit be7bf2c
Show file tree
Hide file tree
Showing 16 changed files with 1,024 additions and 9 deletions.
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ build: dep ## Build binaries
${OPTS} go build ${BUILD_OPTS} -o ./bin/dmsg-monitor ./cmd/dmsg-monitor
${OPTS} go build ${BUILD_OPTS} -o ./bin/tpd-monitor ./cmd/tpd-monitor
${OPTS} go build ${BUILD_OPTS} -o ./bin/vpn-monitor ./cmd/vpn-monitor
${OPTS} go build ${BUILD_OPTS} -o ./bin/skysocks-monitor ./cmd/skysocks-monitor
${OPTS} go build ${BUILD_OPTS} -o ./apps/skysocks-client ./cmd/skysocks-lite-client
${OPTS} go build ${BUILD_OPTS} -o ./bin/public-visor-monitor ./cmd/public-visor-monitor
# yarn --cwd ./pkg/node-visualizer/web build
# rm -rf ./pkg/node-visualizer/api/build/static
Expand All @@ -90,6 +92,8 @@ build-deploy: ## Build for deployment Docker images
go build ${BUILD_OPTS_DEPLOY} -mod=vendor -o /release/dmsg-monitor ./cmd/dmsg-monitor
go build ${BUILD_OPTS_DEPLOY} -mod=vendor -o /release/tpd-monitor ./cmd/tpd-monitor
go build ${BUILD_OPTS_DEPLOY} -mod=vendor -o /release/vpn-monitor ./cmd/vpn-monitor
go build ${BUILD_OPTS_DEPLOY} -mod=vendor -o /release/skysocks-monitor ./cmd/skysocks-monitor
go build ${BUILD_OPTS_DEPLOY} -mod=vendor -o /release/skysocks-client ./cmd/skysocks-lite-client
go build ${BUILD_OPTS_DEPLOY} -mod=vendor -o /release/public-visor-monitor ./cmd/public-visor-monitor

build-race: dep ## Build binaries
Expand All @@ -106,6 +110,8 @@ build-race: dep ## Build binaries
${OPTS} go build ${BUILD_OPTS} -race -o ./bin/dmsg-monitor ./cmd/dmsg-monitor
${OPTS} go build ${BUILD_OPTS} -race -o ./bin/tpd-monitor ./cmd/tpd-monitor
${OPTS} go build ${BUILD_OPTS} -race -o ./bin/vpn-monitor ./cmd/vpn-monitor
${OPTS} go build ${BUILD_OPTS} -race -o ./bin/skysocks-monitor ./cmd/skysocks-monitor
${OPTS} go build ${BUILD_OPTS} -race -o ./bin/skysocks-client ./cmd/skysocks-lite-client
${OPTS} go build ${BUILD_OPTS} -race -o ./bin/public-visor-monitor ./cmd/public-visor-monitor

install: ## Install route-finder, transport-discovery, address-resolver, sw-env, keys-gen, network-monitor, node-visualizer
Expand Down
3 changes: 3 additions & 0 deletions cmd/skysocks-lite-client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Skywire Skysocks lite client app

`skysocks-lite-client` app implements lite client for the skysocks use in skysocks-monitor.
130 changes: 130 additions & 0 deletions cmd/skysocks-lite-client/skysocks-lite-client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// Package main cmd/skysocks-lite-client/skysocks-lite-client.go
package main

import (
"context"
"errors"
"flag"
"fmt"
"io"
"net"
"os"
"time"

"github.com/skycoin/skywire-services/internal/skysocks"
"github.com/skycoin/skywire-utilities/pkg/buildinfo"
"github.com/skycoin/skywire-utilities/pkg/cipher"
"github.com/skycoin/skywire-utilities/pkg/netutil"
"github.com/skycoin/skywire/pkg/app"
"github.com/skycoin/skywire/pkg/app/appnet"
"github.com/skycoin/skywire/pkg/app/appserver"
"github.com/skycoin/skywire/pkg/routing"
"github.com/skycoin/skywire/pkg/visor/visorconfig"
)

const (
netType = appnet.TypeSkynet
socksPort = routing.Port(3)
)

var r = netutil.NewRetrier(nil, time.Second, netutil.DefaultMaxBackoff, 0, 1)

func dialServer(ctx context.Context, appCl *app.Client, pk cipher.PubKey) (net.Conn, error) {
appCl.SetDetailedStatus(appserver.AppDetailedStatusStarting) //nolint
var conn net.Conn
err := r.Do(ctx, func() error {
var err error
conn, err = appCl.Dial(appnet.Addr{
Net: netType,
PubKey: pk,
Port: socksPort,
})
return err
})
if err != nil {
return nil, err
}

return conn, nil
}

func main() {
appCl := app.NewClient(nil)
defer appCl.Close()

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

if _, err := buildinfo.Get().WriteTo(os.Stdout); err != nil {
print(fmt.Sprintf("Failed to output build info: %v\n", err))
}

var addr = flag.String("addr", visorconfig.SkysocksClientAddr, "Client address to listen on")
var serverPK = flag.String("srv", "", "PubKey of the server to connect to")
flag.Parse()

if *serverPK == "" {
err := errors.New("Empty server PubKey. Exiting")
print(fmt.Sprintf("%v\n", err))
setAppErr(appCl, err)
os.Exit(1)
}

pk := cipher.PubKey{}
if err := pk.UnmarshalText([]byte(*serverPK)); err != nil {
print(fmt.Sprintf("Invalid server PubKey: %v\n", err))
setAppErr(appCl, err)
os.Exit(1)
}
defer setAppStatus(appCl, appserver.AppDetailedStatusStopped)
setAppPort(appCl, appCl.Config().RoutingPort)
for {
conn, err := dialServer(ctx, appCl, pk)
if err != nil {
print(fmt.Sprintf("Failed to dial to a server: %v\n", err))
setAppErr(appCl, err)
os.Exit(1)
}

fmt.Printf("Connected to %v\n", pk)
client, err := skysocks.NewClient(conn, appCl)
if err != nil {
print(fmt.Sprintf("Failed to create a new client: %v\n", err))
setAppErr(appCl, err)
os.Exit(1)
}

fmt.Printf("Serving proxy client %v\n", *addr)
setAppStatus(appCl, appserver.AppDetailedStatusRunning)

if err := client.ListenAndServe(*addr); err != nil {
print(fmt.Sprintf("Error serving proxy client: %v\n", err))
}

// need to filter this out, cause usually client failure means app conn is already closed
if err := conn.Close(); err != nil && err != io.ErrClosedPipe {
print(fmt.Sprintf("Error closing app conn: %v\n", err))
}

fmt.Println("Reconnecting to skysocks server")
setAppStatus(appCl, appserver.AppDetailedStatusReconnecting)
}
}

func setAppErr(appCl *app.Client, err error) {
if appErr := appCl.SetError(err.Error()); appErr != nil {
print(fmt.Sprintf("Failed to set error %v: %v\n", err, appErr))
}
}

func setAppStatus(appCl *app.Client, status appserver.AppDetailedStatus) {
if err := appCl.SetDetailedStatus(string(status)); err != nil {
print(fmt.Sprintf("Failed to set status %v: %v\n", status, err))
}
}

func setAppPort(appCl *app.Client, port routing.Port) {
if err := appCl.SetAppPort(port); err != nil {
print(fmt.Sprintf("Failed to set port %v: %v\n", port, err))
}
}
16 changes: 16 additions & 0 deletions cmd/skysocks-monitor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Skysocks Monitor

## API endpoints

### GET `/health`<br>
Gets the health info of the service. e.g.
```
{
"build_info": {
"version": "v1.0.1-267-ge1617c5b",
"commit": "e1617c5b0121182cfd2b610dc518e4753e56440e",
"date": "2022-10-25T11:01:52Z"
},
"started_at": "2022-10-25T11:10:45.152629597Z"
}
```
128 changes: 128 additions & 0 deletions cmd/skysocks-monitor/commands/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Package commands cmd/skysocks-monitor/commands/root.go
package commands

import (
"context"
"log"
"os"
"time"

cc "github.com/ivanpirog/coloredcobra"
"github.com/skycoin/skywire-utilities/pkg/buildinfo"
"github.com/skycoin/skywire-utilities/pkg/cipher"
"github.com/skycoin/skywire-utilities/pkg/cmdutil"
"github.com/skycoin/skywire-utilities/pkg/logging"
"github.com/skycoin/skywire-utilities/pkg/tcpproxy"
"github.com/spf13/cobra"

"github.com/skycoin/skywire-services/pkg/skysocks-monitor/api"
)

var (
confPath string
addr string
tag string
sleepDeregistration time.Duration
)

func init() {
RootCmd.Flags().StringVarP(&addr, "addr", "a", ":9081", "address to bind to.\033[0m")
RootCmd.Flags().DurationVarP(&sleepDeregistration, "sleep-deregistration", "s", 10, "Sleep time for derigstration process in minutes\033[0m")
RootCmd.Flags().StringVarP(&confPath, "config", "c", "skysocks-monitor.json", "config file location.\033[0m")
RootCmd.Flags().StringVar(&tag, "tag", "skysocks_monitor", "logging tag\033[0m")
var helpflag bool
RootCmd.SetUsageTemplate(help)
RootCmd.PersistentFlags().BoolVarP(&helpflag, "help", "h", false, "help for skysocks-monitor")
RootCmd.SetHelpCommand(&cobra.Command{Hidden: true})
RootCmd.PersistentFlags().MarkHidden("help") //nolint
}

// RootCmd contains the root command
var RootCmd = &cobra.Command{
Use: "skysocksmon",
Short: "Skysocks monitor.",
Long: `
┌─┐┬┌─┬ ┬┌─┐┌─┐┌─┐┬┌─┌─┐ ┌┬┐┌─┐┌┐┌┬┌┬┐┌─┐┬─┐
└─┐├┴┐└┬┘└─┐│ ││ ├┴┐└─┐───││││ │││││ │ │ │├┬┘
└─┘┴ ┴ ┴ └─┘└─┘└─┘┴ ┴└─┘ ┴ ┴└─┘┘└┘┴ ┴ └─┘┴└─`,
SilenceErrors: true,
SilenceUsage: true,
DisableSuggestions: true,
DisableFlagsInUseLine: true,
Version: buildinfo.Version(),
Run: func(_ *cobra.Command, _ []string) {
visorBuildInfo := buildinfo.Get()
if _, err := visorBuildInfo.WriteTo(os.Stdout); err != nil {
log.Printf("Failed to output build info: %v", err)
}

mLogger := logging.NewMasterLogger()
conf := api.InitConfig(confPath, mLogger)

srvURLs := api.ServicesURLs{
SD: conf.Launcher.ServiceDisc,
UT: conf.UptimeTracker.Addr,
}

logger := mLogger.PackageLogger("skysocks_monitor")

logger.WithField("addr", addr).Info("Serving discovery API...")

smSign, _ := cipher.SignPayload([]byte(conf.PK.Hex()), conf.SK) //nolint

smConfig := api.Config{
PK: conf.PK,
SK: conf.SK,
Sign: smSign,
}

smAPI := api.New(logger, srvURLs, smConfig)

ctx, cancel := cmdutil.SignalContext(context.Background(), logger)
defer cancel()

go smAPI.InitDeregistrationLoop(ctx, conf, sleepDeregistration)

go func() {
if err := tcpproxy.ListenAndServe(addr, smAPI); err != nil {
logger.Errorf("serve: %v", err)
cancel()
}
}()

<-ctx.Done()
if err := smAPI.Visor.Close(); err != nil {
logger.WithError(err).Error("Visor closed with error.")
}
},
}

// Execute executes root CLI command.
func Execute() {
cc.Init(&cc.Config{
RootCmd: RootCmd,
Headings: cc.HiBlue + cc.Bold, //+ cc.Underline,
Commands: cc.HiBlue + cc.Bold,
CmdShortDescr: cc.HiBlue,
Example: cc.HiBlue + cc.Italic,
ExecName: cc.HiBlue + cc.Bold,
Flags: cc.HiBlue + cc.Bold,
//FlagsDataType: cc.HiBlue,
FlagsDescr: cc.HiBlue,
NoExtraNewlines: true,
NoBottomNewline: true,
})
if err := RootCmd.Execute(); err != nil {
log.Fatal("Failed to execute command: ", err)
}
}

const help = "Usage:\r\n" +
" {{.UseLine}}{{if .HasAvailableSubCommands}}{{end}} {{if gt (len .Aliases) 0}}\r\n\r\n" +
"{{.NameAndAliases}}{{end}}{{if .HasAvailableSubCommands}}\r\n\r\n" +
"Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand)}}\r\n " +
"{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}\r\n\r\n" +
"Flags:\r\n" +
"{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}\r\n\r\n" +
"Global Flags:\r\n" +
"{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}\r\n\r\n"
8 changes: 8 additions & 0 deletions cmd/skysocks-monitor/skysocks-monitor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Package main cmd/skysocks-monitor/skysocks-monitor.go
package main

import "github.com/skycoin/skywire-services/cmd/skysocks-monitor/commands"

func main() {
commands.Execute()
}
12 changes: 6 additions & 6 deletions cmd/tpd-monitor/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ var (
func init() {
RootCmd.Flags().StringVarP(&addr, "addr", "a", ":9080", "address to bind to.\033[0m")
RootCmd.Flags().DurationVarP(&sleepDeregistration, "sleep-deregistration", "s", 10, "Sleep time for deregistration process in minutes\033[0m")
RootCmd.Flags().StringVarP(&confPath, "config", "c", "dmsg-monitor.json", "config file location.\033[0m")
RootCmd.Flags().StringVarP(&confPath, "config", "c", "tpd-monitor.json", "config file location.\033[0m")
RootCmd.Flags().StringVarP(&logLvl, "loglvl", "l", "info", "set log level one of: info, error, warn, debug, trace, panic")
RootCmd.Flags().StringVar(&dmsgURL, "dmsg-url", "", "url to dmsg data.\033[0m")
RootCmd.Flags().StringVar(&tpdURL, "tpd-url", "", "url to transport discovery.\033[0m")
Expand Down Expand Up @@ -105,26 +105,26 @@ var RootCmd = &cobra.Command{

monitorSign, _ := cipher.SignPayload([]byte(conf.PK.Hex()), conf.SK) //nolint

var monitorConfig api.DMSGMonitorConfig
var monitorConfig api.TpdMonitorConfig
monitorConfig.PK = conf.PK
monitorConfig.Sign = monitorSign

dmsgMonitorAPI := api.New(logger, srvURLs, monitorConfig)
tpdMonitorAPI := api.New(logger, srvURLs, monitorConfig)

ctx, cancel := cmdutil.SignalContext(context.Background(), logger)
defer cancel()

go dmsgMonitorAPI.InitDeregistrationLoop(ctx, conf, sleepDeregistration)
go tpdMonitorAPI.InitDeregistrationLoop(ctx, conf, sleepDeregistration)

go func() {
if err := tcpproxy.ListenAndServe(addr, dmsgMonitorAPI); err != nil {
if err := tcpproxy.ListenAndServe(addr, tpdMonitorAPI); err != nil {
logger.Errorf("serve: %v", err)
cancel()
}
}()

<-ctx.Done()
if err := dmsgMonitorAPI.Visor.Close(); err != nil {
if err := tpdMonitorAPI.Visor.Close(); err != nil {
logger.WithError(err).Error("Visor closed with error.")
}
},
Expand Down
Loading

0 comments on commit be7bf2c

Please sign in to comment.