network enhanecment / refactor (#361)

* chore(network): improve connectivity check

* refactor(network): rewrite network and timesync component

* feat(display): show cloud connection status

* chore: change logging verbosity

* chore(websecure): update log message

* fix(ota): validate root certificate when downloading update

* feat(ui): add network settings tab

* fix(display): cloud connecting animation

* fix: golintci issues

* feat: add network settings tab

* feat(timesync): query servers in parallel

* refactor(network): move to internal/network package

* feat(timesync): add metrics

* refactor(log): move log to internal/logging package

* refactor(mdms): move mdns to internal/mdns package

* feat(developer): add pprof endpoint

* feat(logging): add a simple logging streaming endpoint

* fix(mdns): do not start mdns until network is up

* feat(network): allow users to update network settings from ui

* fix(network): handle errors when net.IPAddr is nil

* fix(mdns): scopedLogger SIGSEGV

* fix(dhcp): watch directory instead of file to catch fsnotify.Create event

* refactor(nbd): move platform-specific code to different files

* refactor(native): move platform-specific code to different files

* chore: fix linter issues

* chore(dev_deploy): allow to override PION_LOG_TRACE
This commit is contained in:
Aveline
2025-04-16 01:39:23 +02:00
committed by GitHub
parent 2b2a14204d
commit 189b84380b
71 changed files with 4938 additions and 825 deletions

View File

@@ -139,11 +139,40 @@ var (
)
)
type CloudConnectionState uint8
const (
CloudConnectionStateNotConfigured CloudConnectionState = iota
CloudConnectionStateDisconnected
CloudConnectionStateConnecting
CloudConnectionStateConnected
)
var (
cloudConnectionState CloudConnectionState = CloudConnectionStateNotConfigured
cloudConnectionStateLock = &sync.Mutex{}
cloudDisconnectChan chan error
cloudDisconnectLock = &sync.Mutex{}
)
func setCloudConnectionState(state CloudConnectionState) {
cloudConnectionStateLock.Lock()
defer cloudConnectionStateLock.Unlock()
if cloudConnectionState == CloudConnectionStateDisconnected &&
(config.CloudToken == "" || config.CloudURL == "") {
state = CloudConnectionStateNotConfigured
}
previousState := cloudConnectionState
cloudConnectionState = state
go waitCtrlAndRequestDisplayUpdate(
previousState != state,
)
}
func wsResetMetrics(established bool, sourceType string, source string) {
metricConnectionLastPingTimestamp.WithLabelValues(sourceType, source).Set(-1)
metricConnectionLastPingDuration.WithLabelValues(sourceType, source).Set(-1)
@@ -285,6 +314,8 @@ func runWebsocketClient() error {
wsURL.Scheme = "wss"
}
setCloudConnectionState(CloudConnectionStateConnecting)
header := http.Header{}
header.Set("X-Device-ID", GetDeviceID())
header.Set("X-App-Version", builtAppVersion)
@@ -302,20 +333,26 @@ func runWebsocketClient() error {
c, resp, err := websocket.Dial(dialCtx, wsURL.String(), &websocket.DialOptions{
HTTPHeader: header,
OnPingReceived: func(ctx context.Context, payload []byte) bool {
scopedLogger.Info().Bytes("payload", payload).Int("length", len(payload)).Msg("ping frame received")
scopedLogger.Debug().Bytes("payload", payload).Int("length", len(payload)).Msg("ping frame received")
metricConnectionTotalPingReceivedCount.WithLabelValues("cloud", wsURL.Host).Inc()
metricConnectionLastPingReceivedTimestamp.WithLabelValues("cloud", wsURL.Host).SetToCurrentTime()
setCloudConnectionState(CloudConnectionStateConnected)
return true
},
})
// get the request id from the response header
connectionId := resp.Header.Get("X-Request-ID")
if connectionId == "" {
connectionId = resp.Header.Get("Cf-Ray")
var connectionId string
if resp != nil {
// get the request id from the response header
connectionId = resp.Header.Get("X-Request-ID")
if connectionId == "" {
connectionId = resp.Header.Get("Cf-Ray")
}
}
if connectionId == "" {
connectionId = uuid.New().String()
scopedLogger.Warn().
@@ -332,6 +369,8 @@ func runWebsocketClient() error {
if err != nil {
if errors.Is(err, context.Canceled) {
cloudLogger.Info().Msg("websocket connection canceled")
setCloudConnectionState(CloudConnectionStateDisconnected)
return nil
}
return err
@@ -450,14 +489,14 @@ func RunWebsocketClient() {
}
// If the network is not up, well, we can't connect to the cloud.
if !networkState.Up {
cloudLogger.Warn().Msg("waiting for network to be up, will retry in 3 seconds")
if !networkState.IsOnline() {
cloudLogger.Warn().Msg("waiting for network to be online, will retry in 3 seconds")
time.Sleep(3 * time.Second)
continue
}
// If the system time is not synchronized, the API request will fail anyway because the TLS handshake will fail.
if isTimeSyncNeeded() && !timeSyncSuccess {
if isTimeSyncNeeded() && !timeSync.IsSyncSuccess() {
cloudLogger.Warn().Msg("system time is not synced, will retry in 3 seconds")
time.Sleep(3 * time.Second)
continue
@@ -520,6 +559,8 @@ func rpcDeregisterDevice() error {
cloudLogger.Info().Msg("device deregistered, disconnecting from cloud")
disconnectCloud(fmt.Errorf("device deregistered"))
setCloudConnectionState(CloudConnectionStateNotConfigured)
return nil
}