2727import GLib from 'gi://GLib' ;
2828import GObject from 'gi://GObject' ;
2929import * as SubProcessModule from './helpers/subprocess.js' ;
30+ import Gio from 'gi://Gio' ;
3031import * as FileModule from './helpers/file.js' ;
3132import { gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js' ;
3233import NM from 'gi://NM' ;
@@ -46,6 +47,8 @@ export const Sensors = GObject.registerClass({
4647 this . _settings = settings ;
4748 this . _sensorIcons = sensorIcons ;
4849
50+ this . _pingCancellable = null ;
51+
4952 this . resetHistory ( ) ;
5053
5154 this . _last_processor = { 'core' : { } , 'speed' : [ ] } ;
@@ -54,6 +57,7 @@ export const Sensors = GObject.registerClass({
5457 this . _addSettingChangedSignal ( 'show-gpu' , this . _reconfigureNvidiaSmiProcess . bind ( this ) ) ;
5558 this . _addSettingChangedSignal ( 'update-time' , this . _reconfigureNvidiaSmiProcess . bind ( this ) ) ;
5659 this . _addSettingChangedSignal ( 'network-public-ip-interval' , ( ) => { this . _lastPublicIPCheck = 0 ; } ) ;
60+ this . _addSettingChangedSignal ( 'network-ping-host' , ( ) => this . _pingCancellable ?. cancel ( ) ) ;
5761 //this._addSettingChangedSignal('include-static-gpu-info', this._reconfigureNvidiaSmiProcess.bind(this));
5862
5963 this . _gpu_drm_vendors = null ;
@@ -338,6 +342,63 @@ export const Sensors = GObject.registerClass({
338342 this . _returnValue ( callback , 'WiFi Signal Level' , signal , 'network' , 'string' ) ;
339343 }
340344 } ) . catch ( err => { } ) ;
345+
346+ this . _pollPing ( value => {
347+ this . _returnValue ( callback , 'Ping' , value , 'network-ping' , 'string' ) ;
348+ } ) ;
349+ }
350+
351+ _pollPing ( callback ) {
352+ let host = this . _settings . get_string ( 'network-ping-host' ) . trim ( ) ;
353+ if ( ! host ) return ;
354+
355+ this . _pingCancellable ?. cancel ( ) ;
356+ this . _pingCancellable = new Gio . Cancellable ( ) ;
357+ let cancellable = this . _pingCancellable ;
358+
359+ let subprocess ;
360+ try {
361+ subprocess = new Gio . Subprocess ( {
362+ argv : [ 'ping' , '-c' , '1' , '-W' , '5' , host ] ,
363+ flags : Gio . SubprocessFlags . STDOUT_PIPE |
364+ Gio . SubprocessFlags . STDERR_PIPE ,
365+ } ) ;
366+ subprocess . init ( null ) ;
367+ } catch ( e ) {
368+ callback ( '?? ms' ) ;
369+ return ;
370+ }
371+
372+ cancellable . connect ( ( ) => subprocess . force_exit ( ) ) ;
373+
374+ subprocess . communicate_utf8_async ( null , cancellable , ( proc , result ) => {
375+ let value = this . _parsePingResult ( proc , result , cancellable ) ;
376+ callback ( value ) ;
377+ } ) ;
378+ }
379+
380+ _parsePingResult ( proc , result , cancellable ) {
381+ let stdout , exitStatus ;
382+ try {
383+ [ , stdout ] = proc . communicate_utf8_finish ( result ) ;
384+ exitStatus = proc . get_exit_status ( ) ;
385+ } catch ( e ) {
386+ let cancelled = cancellable . is_cancelled ( ) ;
387+ return cancelled ? this . _pingTimeoutLabel ( ) : '?? ms' ;
388+ }
389+
390+ if ( exitStatus === 0 && stdout ) {
391+ let match = / t i m e [ = < ] ( [ \d . ] + ) \s * m s / . exec ( stdout ) ;
392+ if ( match )
393+ return `${ parseFloat ( match [ 1 ] ) . toFixed ( 1 ) } ms` ;
394+ }
395+
396+ return exitStatus === 1 ? this . _pingTimeoutLabel ( ) : '?? ms' ;
397+ }
398+
399+ _pingTimeoutLabel ( ) {
400+ let timeoutMs = Math . min ( Math . max ( this . _settings . get_int ( 'update-time' ) , 1 ) , 5 ) * 1000 ;
401+ return `${ timeoutMs } + ms` ;
341402 }
342403
343404 _queryStorage ( callback , dwell ) {
@@ -1066,11 +1127,13 @@ export const Sensors = GObject.registerClass({
10661127 this . _frameMonitorLastTime = 0 ;
10671128 this . _frameMonitorFrameCount = 0 ;
10681129 this . _frameMonitorAccTime = 0 ;
1130+ this . _pingCancellable ?. cancel ( ) ;
10691131 }
10701132
10711133 destroy ( ) {
10721134 this . _destroyFrameMonitor ( ) ;
10731135 this . _terminateNvidiaSmiProcess ( ) ;
1136+ this . _pingCancellable ?. cancel ( ) ;
10741137
10751138 for ( let signal of Object . values ( this . _settingChangedSignals ) )
10761139 this . _settings . disconnect ( signal ) ;
0 commit comments