diff --git a/backend/cmd/config.toml b/backend/cmd/config.toml index af5f4c467..a71056e8f 100644 --- a/backend/cmd/config.toml +++ b/backend/cmd/config.toml @@ -7,9 +7,6 @@ # 3. Toggle the Fault Propagation to your needs (true/false) # 4. Check the TCP configuration and make sure to use the needed Keep Alive settings -# Control Station general configuration -[app] -automatic_window_opening = "" # Leave blank to open no windows (, ethernet-view, control-station, both) # Vehicle Configuration [vehicle] @@ -40,13 +37,6 @@ keep_alive_ms = 1000 # Keep-alive interval in milliseconds ring_buffer_size = 64 # Size of the ring buffer for incoming packets (number of packets, not bytes) packet_chan_size = 16 # Size of the channel buffer -# TFTP Configuration -[tftp] -block_size = 131072 # TFTP block size in bytes (128kB) -retries = 3 # Maximum number of retries before aborting transfer -timeout_ms = 5000 # Timeout between retries in milliseconds -backoff_factor = 2 # Backoff multiplier for retry delays -enable_progress = true # Enable progress callbacks during transfers # Logger Configuration [logging] diff --git a/backend/cmd/dev-config.toml b/backend/cmd/dev-config.toml index 1cbac364a..1a6d3a437 100644 --- a/backend/cmd/dev-config.toml +++ b/backend/cmd/dev-config.toml @@ -9,8 +9,6 @@ # 4. Check the TCP configuration and make sure to use the needed Keep Alive settings # Control Station general configuration -[app] -automatic_window_opening = "" # Leave blank to open no windows (, ethernet-view, control-station, both) # Vehicle Configuration [vehicle] @@ -64,16 +62,6 @@ programable_boards = "/uploadableBoards" connections = "/backend" files = "/" -# TFTP Configuration -[tftp] -block_size = 512 # TFTP block size (512 or 1468 bytes) -retries = 3 # Number of retries for TFTP operations -timeout_ms = 5000 # Timeout for TFTP operations in milliseconds -backoff_factor = 2 # Backoff factor for retries -enable_progress = true # Enable progress updates during transfers - - - # Logging Configuration [logging] time_unit = "us" # Time unit for log timestamps (ns, us, ms, s) diff --git a/backend/cmd/main.go b/backend/cmd/main.go index d202f8e0b..3aa50883b 100644 --- a/backend/cmd/main.go +++ b/backend/cmd/main.go @@ -135,9 +135,6 @@ func main() { } } - // Open browser tabs - openBrowserTabs(config) - // Wait for interrupt signal to gracefully shutdown the backend interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt) diff --git a/backend/cmd/orchestrator.go b/backend/cmd/orchestrator.go index 6d34b064a..e395060df 100644 --- a/backend/cmd/orchestrator.go +++ b/backend/cmd/orchestrator.go @@ -15,7 +15,6 @@ import ( "github.com/HyperloopUPV-H8/h9-backend/pkg/logger" data_logger "github.com/HyperloopUPV-H8/h9-backend/pkg/logger/data" order_logger "github.com/HyperloopUPV-H8/h9-backend/pkg/logger/order" - "github.com/pkg/browser" trace "github.com/rs/zerolog/log" ) @@ -148,16 +147,3 @@ func setUpLogger(config config.Config) (*logger.Logger, abstraction.SubloggersMa return loggerHandler, subloggers } - -func openBrowserTabs(config config.Config) { - - switch config.App.AutomaticWindowOpening { - case "ethernet-view": - browser.OpenURL("http://" + config.Server["ethernet-view"].Addr) - case "control-station": - browser.OpenURL("http://" + config.Server["control-station"].Addr) - case "both": - browser.OpenURL("http://" + config.Server["ethernet-view"].Addr) - browser.OpenURL("http://" + config.Server["control-station"].Addr) - } -} diff --git a/backend/cmd/setup_transport.go b/backend/cmd/setup_transport.go index 82bd10dc9..f148a27b7 100644 --- a/backend/cmd/setup_transport.go +++ b/backend/cmd/setup_transport.go @@ -64,16 +64,19 @@ func configureTCPClientTransport( i := 0 // count // map of remote server addresses to transport targets for boards not present in vehicle config - serverTargets := make(map[string]abstraction.TransportTarget) for _, board := range podData.Boards { + + // Skip boards not in config.Vehicle.Boards to avoid unnecessary TCP clients and potential connection issues if !common.Contains(config.Vehicle.Boards, board.Name) { - serverTargets[fmt.Sprintf("%s:%d", adj.Info.Addresses[board.Name], adj.Info.Ports[TcpClient])] = abstraction.TransportTarget(board.Name) continue } + + // Resolve local TCP client address with incremental port to avoid conflicts backendTcpClientAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", adj.Info.Addresses[BACKEND], adj.Info.Ports[TcpClient]+uint16(i))) if err != nil { - panic("Failed to resolve local backend TCP client address") + trace.Fatal().Err(err).Msg("failed to resolve local backend TCP client address: " + err.Error()) } + // Create TCP client config with custom parameters from config clientConfig := tcp.NewClientConfig(backendTcpClientAddr) diff --git a/backend/go.mod b/backend/go.mod index 2571668d5..c4603d2ef 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -9,8 +9,6 @@ require ( github.com/gorilla/websocket v1.5.0 github.com/jmaralo/sntp v0.0.0-20240116111937-45a0a3419272 github.com/pelletier/go-toml/v2 v2.0.7 - github.com/pin/tftp/v3 v3.0.0 - github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c github.com/rs/zerolog v1.29.0 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 ) @@ -41,6 +39,4 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect ) -require ( - golang.org/x/net v0.38.0 // indirect -) +require golang.org/x/net v0.38.0 // indirect diff --git a/backend/go.sum b/backend/go.sum index c9928069c..4c13f9296 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -23,8 +23,6 @@ github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcej github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= @@ -46,8 +44,6 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= -github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jmaralo/sntp v0.0.0-20240116111937-45a0a3419272 h1:dtQzdBn2P781UxyDPZd1tv4QE29ffpnmJ15qBkXHypY= @@ -72,12 +68,8 @@ github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us= github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= -github.com/pin/tftp/v3 v3.0.0 h1:o9cQpmWBSbgiaYXuN+qJAB12XBIv4dT7OuOONucn2l0= -github.com/pin/tftp/v3 v3.0.0/go.mod h1:xwQaN4viYL019tM4i8iecm++5cGxSqen6AJEOEyEI0w= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -123,7 +115,6 @@ golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -150,7 +141,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/backend/internal/config/config_types.go b/backend/internal/config/config_types.go index ecf78c783..32260e5aa 100644 --- a/backend/internal/config/config_types.go +++ b/backend/internal/config/config_types.go @@ -6,10 +6,6 @@ import ( "github.com/HyperloopUPV-H8/h9-backend/pkg/logger" ) -type App struct { - AutomaticWindowOpening string `toml:"automatic_window_opening"` -} - type Adj struct { Branch string `toml:"branch"` Validate bool `toml:"validate"` @@ -19,14 +15,6 @@ type Transport struct { PropagateFault bool `toml:"propagate_fault"` } -type TFTP struct { - BlockSize int `toml:"block_size"` - Retries int `toml:"retries"` - TimeoutMs int `toml:"timeout_ms"` - BackoffFactor int `toml:"backoff_factor"` - EnableProgress bool `toml:"enable_progress"` -} - type TCP struct { BackoffMinMs int `toml:"backoff_min_ms"` BackoffMaxMs int `toml:"backoff_max_ms"` @@ -47,12 +35,10 @@ type Logging struct { } type Config struct { - App App Vehicle vehicle.Config Server server.Config Adj Adj Transport Transport - TFTP TFTP TCP TCP UDP UDP Logging Logging diff --git a/backend/pkg/transport/network/tcp/client.go b/backend/pkg/transport/network/tcp/client.go index 2fb683820..038d68fa9 100644 --- a/backend/pkg/transport/network/tcp/client.go +++ b/backend/pkg/transport/network/tcp/client.go @@ -1,10 +1,8 @@ package tcp import ( - "errors" "fmt" "net" - "syscall" "time" "github.com/rs/zerolog" @@ -38,6 +36,7 @@ func (client *Client) Dial() (net.Conn, error) { var err error var conn net.Conn + client.currentRetries = 0 client.logger.Info().Msg("dialing") for client.config.MaxConnectionRetries <= 0 || client.currentRetries < client.config.MaxConnectionRetries { @@ -64,8 +63,8 @@ func (client *Client) Dial() (net.Conn, error) { return nil, client.config.Context.Err() } - // Check if we should retry this error - if netErr, ok := err.(net.Error); !client.config.TryReconnect || (!errors.Is(err, syscall.ECONNREFUSED) && (!ok || !netErr.Timeout())) { + // If reconnection is disabled, bail out immediately on any error + if !client.config.TryReconnect { client.logger.Error().Stack().Err(err).Msg("failed with non-retryable error") return nil, err } diff --git a/backend/pkg/transport/network/tcp/config.go b/backend/pkg/transport/network/tcp/config.go index 2d0c6a39d..4403bd788 100644 --- a/backend/pkg/transport/network/tcp/config.go +++ b/backend/pkg/transport/network/tcp/config.go @@ -24,7 +24,13 @@ func NewClientConfig(laddr net.Addr) ClientConfig { Dialer: net.Dialer{ Timeout: time.Second, LocalAddr: laddr, - KeepAlive: time.Second, // Going under 1 second won't work in most systems + KeepAlive: -1, // managed via KeepAliveConfig + KeepAliveConfig: net.KeepAliveConfig{ + Enable: true, + Idle: time.Second, + Interval: time.Second, + Count: 3, + }, }, Context: context.TODO(), @@ -69,7 +75,13 @@ type ServerConfig struct { func NewServerConfig() ServerConfig { return ServerConfig{ ListenConfig: net.ListenConfig{ - KeepAlive: time.Second, + KeepAlive: -1, // managed via KeepAliveConfig + KeepAliveConfig: net.KeepAliveConfig{ + Enable: true, + Idle: time.Second, + Interval: time.Second, + Count: 3, + }, }, Context: context.TODO(), } diff --git a/backend/pkg/transport/network/tcp/conn.go b/backend/pkg/transport/network/tcp/conn.go index 35575bf34..4786c9e5d 100644 --- a/backend/pkg/transport/network/tcp/conn.go +++ b/backend/pkg/transport/network/tcp/conn.go @@ -21,7 +21,10 @@ func WithErrChan(conn net.Conn) (net.Conn, <-chan error) { func (conn *connWithErr) Read(b []byte) (n int, err error) { n, err = conn.Conn.Read(b) if err != nil && !errors.Is(err, net.ErrClosed) { - conn.errors <- err + select { + case conn.errors <- err: + default: + } } return } @@ -29,12 +32,14 @@ func (conn *connWithErr) Read(b []byte) (n int, err error) { func (conn *connWithErr) Write(b []byte) (n int, err error) { n, err = conn.Conn.Write(b) if err != nil && !errors.Is(err, net.ErrClosed) { - conn.errors <- err + select { + case conn.errors <- err: + default: + } } return } func (conn *connWithErr) Close() error { - close(conn.errors) return conn.Conn.Close() } diff --git a/backend/pkg/transport/transport.go b/backend/pkg/transport/transport.go index cac9046c9..309a2b32c 100644 --- a/backend/pkg/transport/transport.go +++ b/backend/pkg/transport/transport.go @@ -15,7 +15,6 @@ import ( "github.com/HyperloopUPV-H8/h9-backend/pkg/transport/network/udp" "github.com/HyperloopUPV-H8/h9-backend/pkg/transport/packet/data" "github.com/HyperloopUPV-H8/h9-backend/pkg/transport/presentation" - "github.com/pin/tftp/v3" "github.com/rs/zerolog" ) @@ -35,8 +34,6 @@ type Transport struct { ipToTarget map[string]abstraction.TransportTarget idToTarget map[abstraction.PacketId]abstraction.TransportTarget - tftp *tftp.Client - propagateFault bool api abstraction.TransportAPI @@ -58,7 +55,7 @@ func (transport *Transport) HandleClient(config tcp.ClientConfig, remote string) client := tcp.NewClient(remote, config, transport.logger) clientLogger := transport.logger.With().Str("remoteAddress", remote).Logger() defer clientLogger.Warn().Msg("abort connection") - var hasConnected = false + hasConnected := false for { conn, err := client.Dial() @@ -129,7 +126,8 @@ func (transport *Transport) handleTCPConn(conn net.Conn) error { return err } - connectionLogger := transport.logger.With().Str("remoteAddress", conn.RemoteAddr().String()).Str("target", string(target)).Logger() + connectionLogger := transport.logger.With(). + Str("remoteAddress", conn.RemoteAddr().String()).Str("target", string(target)).Logger() connectionLogger.Info().Msg("new connection") if err := transport.rejectIfConnectedTCPConn(target, conn, connectionLogger); err != nil { @@ -146,6 +144,7 @@ func (transport *Transport) handleTCPConn(conn net.Conn) error { cleanupConn := transport.registerTCPConn(target, conn, connectionLogger) defer cleanupConn() + // Notify vehicle of connection status. transport.api.ConnectionUpdate(target, true) defer transport.api.ConnectionUpdate(target, false) diff --git a/go.work b/go.work index 957518330..521811c76 100644 --- a/go.work +++ b/go.work @@ -2,5 +2,4 @@ go 1.23.1 use ( ./backend - ./packet-sender )