Question about remoting the GDM greeter session

So, I’m yet another guy working on Chrome Remote Desktop Wayland support. I have read this thread and Headless remote sessions in GNOME, Part 2 and Headless remote sessions in GNOME, Part 3. I just want to check if my understanding of how Gnome Remote Desktop (GRD) handles the session handover is correct, and how we CRD, which does not use RDP as the underlying protocol, can achieve the same thing.

IIUC the way GRD works is:

  1. GRD calls some GDM private API to create a headless greeter session and a corresponding RDP connection for it. The API returns a remote_id and session_id to GRD

  2. GRD uses RDP’s ServerRedirection feature to redirect the GRD/RDP client to the new greeter RDP session

  3. User completes login within the greeter session, via the redirected RDP session.

  4. GDM creates a new headless user session and the corresponding new RDP connection for it.

  5. GRD redirects its client to the new user RDP connection.

Presumably CRD cannot replicate this flow. We could create something to bridge the RDP connection to the CRD protocol (which is essentially WebRTC), but that is going to be a big maintenance burden.

So, my questions are:

  1. Am I correct that GDM will create a virtual monitor for both the greeter session, and the user session?
  2. Am I correct that I can just use the Remote Desktop & ScreenCast Portals, or Mutter’s private APIs to capture the virtual monitors stated in Q1?
  3. Assuming Q1 and Q2 are correct. Do I create a monitor stream (e.g. RecordMonitor) as opposed to a virtual stream (e.g. RecordVirtual) to capture the virtual monitor?
  4. Based on our experience, capturing a virtual monitor with a monitor stream results in very bad performance, and the virtual monitor will not be resizable via PipeWire. Is it possible to prevent GDM from creating any (GDM-managed) virtual monitors, or are they simply not created if no clients have connected to the RDP session?

GRD calls some GDM API to create a headless greeter session. Another GRD daemon is automatically launched as part of it, and the RDP client is told to reconnect in a way that lets this new GRD daemon to continue the RDP session.

This is indeed how the first GRD server handles handover to the second.

Pretty much, yes.

Why do you make such an assumption? Within GDM, there is nothing specific to RDP, it’s all implemented in GRD. As long as you can move a CRD client session between daemons/services (system service to greeter service to user service), with whatever method that CRD makes possible, you should be able to replicate the same setup.

If not, you can possibly replicate something similar, except with some internal IPC abstracting any remote desktop protocol bits, with a system level broker daemon of sorts.

GDM does not create any virtual monitors, it is GRD that does this. The greeter session is practically a regular remote desktop session, only that the session runs as a GDM greeter user. GRD handles creation of virtual monitors, e.g. according to RDP client needs.

Technically you can right now use Mutter’s private API, simply because there is currently no alternative for “remote desktop” use case where the session is primarily accessed remotely, but the idea is to migrate to a vendorless equivalent eventually, that is meant to replace the private APIs for remote desktop use cases. If you’re sharing a screen of an active physical session, you should still use the portals, and not the private APIs. The aim is keep the private API usable for the actual remote desktop use case until there has been something to migrate too for a while, which there currently isn’t.

Use RecordVirtual to create and capture a virtual monitor. RecordMonitor is for capturing an existing monitor, be it virtual or not.

GDM does not create any virtual monitors. For a fully remote session, it’s the remote desktop server (e.g. GRD) that creates them.

Thanks for the clarification! I somehow had the impression that GDM was responsible for creating and managing the new RDP connections, but it sounds like all the RDP stuff is handled by GRD. In that case, it should be easy to implement by CRD.

One more question.. Are remote_id and session_id essentially used for identifying sessions in a single transition? For example, when the user logs in on the greeter, some DBus property with remote_id in its path will be changed to have the session_id for the new user session?

GDM is in charge of creating the headless graphical sessions (aka gnome-session starting gnome-shell in a headless way).

When a new RDP client connects to the system, GRD requests GDM to create a new headless graphical session, and it passes remote_id to identify the RDP client.

GDM then creates the session and exposes a dbus iface called RemoteDisplay which has this remote_id and the session_id of the headless session.

GRD gets that info to know that a headless session has been created for a specific RDP client. Then creates a dbus iface called Handover with the session_id to perform the handover of the RDP client to the new headless session.

It’s worth mentioning that in this design, we have two types of RDP servers: there’s a system-level daemon (dispatcher daemon) and a user-level daemon (handover daemon).

It’s the dispatcher daemon, the one in charge of requesting GDM to create a new session, exposing Handover ifaces, and passing the RDP client to handover daemons. The handover daemons consume the Handover iface.

The handover happens twice: the first one from the first connection to the greeter, the second one from the greeter to the user session.

This is very useful information. Thank you so much!