[gnome-remote-desktop/gnome-42] rdp/nw-auto: Add APIs for bandwidth measurement
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-remote-desktop/gnome-42] rdp/nw-auto: Add APIs for bandwidth measurement
- Date: Thu, 19 May 2022 18:36:10 +0000 (UTC)
commit ba405d149ffe5af964c4deed815944b3207684ac
Author: Pascal Nowack <Pascal Nowack gmx de>
Date: Tue May 17 12:09:28 2022 +0200
rdp/nw-auto: Add APIs for bandwidth measurement
mstsc has a network indicator icon, which is only shown, when the
server side also sends Network Characteristics Result PDUs containing a
bandwidth measurement result.
Currently, gnome-remote-desktop does not measure the bandwidth, so add
additional APIs to be able to perform these measurements.
Measuring the bandwidth is useful for screen updates.
With the graphics pipeline, progressive rendering is possible, which is
helpful for low bandwidth scenarios.
Currently, it is not yet implemented, but will hopefully be in the
future.
Since sending screen updates in the graphics pipeline is done in an
async way, add an additional API to be able to queue a bandwidth
measure stop.
To be able to be notified of such queued bandwidth measure stop, add an
API to retrieve the associated WinPR event handle.
src/grd-rdp-network-autodetection.c | 115 ++++++++++++++++++++++++++++++++++++
src/grd-rdp-network-autodetection.h | 8 +++
2 files changed, 123 insertions(+)
---
diff --git a/src/grd-rdp-network-autodetection.c b/src/grd-rdp-network-autodetection.c
index f089f068..edf11af4 100644
--- a/src/grd-rdp-network-autodetection.c
+++ b/src/grd-rdp-network-autodetection.c
@@ -37,6 +37,14 @@ typedef enum _PingInterval
PING_INTERVAL_LOW,
} PingInterval;
+typedef enum _BwMeasureState
+{
+ BW_MEASURE_STATE_NONE,
+ BW_MEASURE_STATE_PENDING_STOP,
+ BW_MEASURE_STATE_QUEUED_STOP,
+ BW_MEASURE_STATE_PENDING_RESULTS,
+} BwMeasureState;
+
typedef struct _PingInfo
{
uint16_t sequence_number;
@@ -70,6 +78,11 @@ struct _GrdRdpNetworkAutodetection
GQueue *round_trip_times;
PingInterval ping_interval;
+ GMutex bw_measure_mutex;
+ uint32_t measured_bandwidth;
+ BwMeasureState bw_measure_state;
+ HANDLE bw_measure_stop_event;
+
int64_t last_nw_char_res_notification_us;
uint16_t next_sequence_number;
@@ -267,6 +280,59 @@ grd_rdp_network_autodetection_set_rtt_consumer_necessity (GrdRdpNetworkAutodetec
g_mutex_unlock (&network_autodetection->consumer_mutex);
}
+gboolean
+grd_rdp_network_autodetection_try_bw_measure_start (GrdRdpNetworkAutodetection *network_autodetection)
+{
+ rdpAutoDetect *rdp_autodetect = network_autodetection->rdp_autodetect;
+ g_autoptr (GMutexLocker) locker = NULL;
+
+ locker = g_mutex_locker_new (&network_autodetection->bw_measure_mutex);
+ if (network_autodetection->bw_measure_state != BW_MEASURE_STATE_NONE)
+ return FALSE;
+
+ network_autodetection->bw_measure_state = BW_MEASURE_STATE_PENDING_STOP;
+ g_clear_pointer (&locker, g_mutex_locker_free);
+
+ rdp_autodetect->BandwidthMeasureStart (network_autodetection->rdp_context,
+ BW_MEASURE_SEQUENCE_NUMBER);
+
+ return TRUE;
+}
+
+void
+grd_rdp_network_autodetection_bw_measure_stop (GrdRdpNetworkAutodetection *network_autodetection)
+{
+ rdpAutoDetect *rdp_autodetect = network_autodetection->rdp_autodetect;
+
+ g_mutex_lock (&network_autodetection->bw_measure_mutex);
+ g_assert (network_autodetection->bw_measure_state == BW_MEASURE_STATE_PENDING_STOP ||
+ network_autodetection->bw_measure_state == BW_MEASURE_STATE_QUEUED_STOP);
+
+ ResetEvent (network_autodetection->bw_measure_stop_event);
+ network_autodetection->bw_measure_state = BW_MEASURE_STATE_PENDING_RESULTS;
+ g_mutex_unlock (&network_autodetection->bw_measure_mutex);
+
+ rdp_autodetect->BandwidthMeasureStop (network_autodetection->rdp_context,
+ BW_MEASURE_SEQUENCE_NUMBER);
+}
+
+void
+grd_rdp_network_autodetection_queue_bw_measure_stop (GrdRdpNetworkAutodetection *network_autodetection)
+{
+ g_mutex_lock (&network_autodetection->bw_measure_mutex);
+ g_assert (network_autodetection->bw_measure_state == BW_MEASURE_STATE_PENDING_STOP);
+
+ SetEvent (network_autodetection->bw_measure_stop_event);
+ network_autodetection->bw_measure_state = BW_MEASURE_STATE_QUEUED_STOP;
+ g_mutex_unlock (&network_autodetection->bw_measure_mutex);
+}
+
+HANDLE
+grd_rdp_network_autodetection_get_bw_measure_stop_event_handle (GrdRdpNetworkAutodetection
*network_autodetection)
+{
+ return network_autodetection->bw_measure_stop_event;
+}
+
static void
track_round_trip_time (GrdRdpNetworkAutodetection *network_autodetection,
int64_t ping_time_us,
@@ -339,6 +405,9 @@ maybe_send_network_characteristics_results (GrdRdpNetworkAutodetection *network_
int64_t current_time_us;
uint16_t sequence_number;
+ if (network_autodetection->measured_bandwidth <= 0)
+ return;
+
if (g_queue_get_length (network_autodetection->round_trip_times) == 0)
return;
@@ -348,6 +417,7 @@ maybe_send_network_characteristics_results (GrdRdpNetworkAutodetection *network_
if (current_time_us - last_notification_us < MIN_NW_CHAR_RES_INTERVAL_US)
return;
+ rdp_autodetect->netCharBandwidth = network_autodetection->measured_bandwidth;
rdp_autodetect->netCharBaseRTT = base_round_trip_time_ms;
rdp_autodetect->netCharAverageRTT = avg_round_trip_time_ms;
@@ -426,6 +496,42 @@ autodetect_rtt_measure_response (rdpContext *rdp_context,
return TRUE;
}
+static BOOL
+autodetect_bw_measure_results (rdpContext *rdp_context,
+ uint16_t sequence_number)
+{
+ RdpPeerContext *rdp_peer_context = (RdpPeerContext *) rdp_context;
+ GrdRdpNetworkAutodetection *network_autodetection =
+ rdp_peer_context->network_autodetection;
+ rdpAutoDetect *rdp_autodetect;
+ g_autoptr (GMutexLocker) locker = NULL;
+ int64_t base_round_trip_time_us;
+ int64_t avg_round_trip_time_us;
+
+ locker = g_mutex_locker_new (&network_autodetection->bw_measure_mutex);
+ if (network_autodetection->bw_measure_state != BW_MEASURE_STATE_PENDING_RESULTS)
+ return TRUE;
+
+ network_autodetection->bw_measure_state = BW_MEASURE_STATE_NONE;
+ g_clear_pointer (&locker, g_mutex_locker_free);
+
+ rdp_autodetect = network_autodetection->rdp_autodetect;
+ if (rdp_autodetect->netCharBandwidth <= 0)
+ return TRUE;
+
+ network_autodetection->measured_bandwidth = rdp_autodetect->netCharBandwidth;
+
+ update_round_trip_time_values (network_autodetection,
+ &base_round_trip_time_us,
+ &avg_round_trip_time_us);
+
+ maybe_send_network_characteristics_results (network_autodetection,
+ base_round_trip_time_us / 1000,
+ avg_round_trip_time_us / 1000);
+
+ return TRUE;
+}
+
GrdRdpNetworkAutodetection *
grd_rdp_network_autodetection_new (rdpContext *rdp_context)
{
@@ -439,6 +545,7 @@ grd_rdp_network_autodetection_new (rdpContext *rdp_context)
network_autodetection->rdp_autodetect = rdp_autodetect;
rdp_autodetect->RTTMeasureResponse = autodetect_rtt_measure_response;
+ rdp_autodetect->BandwidthMeasureResults = autodetect_bw_measure_results;
return network_autodetection;
}
@@ -469,6 +576,8 @@ grd_rdp_network_autodetection_dispose (GObject *object)
g_clear_pointer (&network_autodetection->sequences, g_hash_table_destroy);
+ g_clear_pointer (&network_autodetection->bw_measure_stop_event, CloseHandle);
+
G_OBJECT_CLASS (grd_rdp_network_autodetection_parent_class)->dispose (object);
}
@@ -478,6 +587,7 @@ grd_rdp_network_autodetection_finalize (GObject *object)
GrdRdpNetworkAutodetection *network_autodetection =
GRD_RDP_NETWORK_AUTODETECTION (object);
+ g_mutex_clear (&network_autodetection->bw_measure_mutex);
g_mutex_clear (&network_autodetection->sequence_mutex);
g_mutex_clear (&network_autodetection->consumer_mutex);
g_mutex_clear (&network_autodetection->shutdown_mutex);
@@ -489,6 +599,10 @@ static void
grd_rdp_network_autodetection_init (GrdRdpNetworkAutodetection *network_autodetection)
{
network_autodetection->ping_interval = PING_INTERVAL_NONE;
+ network_autodetection->bw_measure_state = BW_MEASURE_STATE_NONE;
+
+ network_autodetection->bw_measure_stop_event =
+ CreateEvent (NULL, TRUE, FALSE, NULL);
network_autodetection->sequences = g_hash_table_new (NULL, NULL);
network_autodetection->pings = g_queue_new ();
@@ -497,6 +611,7 @@ grd_rdp_network_autodetection_init (GrdRdpNetworkAutodetection *network_autodete
g_mutex_init (&network_autodetection->shutdown_mutex);
g_mutex_init (&network_autodetection->consumer_mutex);
g_mutex_init (&network_autodetection->sequence_mutex);
+ g_mutex_init (&network_autodetection->bw_measure_mutex);
}
static void
diff --git a/src/grd-rdp-network-autodetection.h b/src/grd-rdp-network-autodetection.h
index 81ef3acf..95d31f11 100644
--- a/src/grd-rdp-network-autodetection.h
+++ b/src/grd-rdp-network-autodetection.h
@@ -53,4 +53,12 @@ void grd_rdp_network_autodetection_set_rtt_consumer_necessity (GrdRdpNetworkAuto
GrdRdpNwAutodetectRTTConsumer rtt_consumer,
GrdRdpNwAutodetectRTTNecessity
rtt_necessity);
+gboolean grd_rdp_network_autodetection_try_bw_measure_start (GrdRdpNetworkAutodetection
*network_autodetection);
+
+void grd_rdp_network_autodetection_bw_measure_stop (GrdRdpNetworkAutodetection *network_autodetection);
+
+void grd_rdp_network_autodetection_queue_bw_measure_stop (GrdRdpNetworkAutodetection *network_autodetection);
+
+HANDLE grd_rdp_network_autodetection_get_bw_measure_stop_event_handle (GrdRdpNetworkAutodetection
*network_autodetection);
+
#endif /* GRD_RDP_NETWORK_AUTODETECTION_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]