-
Notifications
You must be signed in to change notification settings - Fork 22
Add skeleton support for VNC server. #113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a few comments, but am also inclined to land it sooner rather than later, and iterate after that.
} | ||
|
||
#[derive(Clone)] | ||
pub struct PropolisVncServer { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style nit: probably don't need 'propolis' in the name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just called it that because there's another type called rfb::VncServer
and I found it confusing. I would prefer to name it not just VncServer
but am down to rename it otherwise.
server/src/lib/vnc.rs
Outdated
// Show a white screen if the guest isn't ready yet. | ||
const LEN: usize = 1024 * 768 * 4; | ||
let mut pixels = vec![0u8; LEN]; | ||
for i in 0..LEN { | ||
pixels[i] = 0xff; | ||
} | ||
let r = Rectangle::new( | ||
0, | ||
0, | ||
1024, | ||
768, | ||
Box::new(RawEncoding::new(pixels)), | ||
); | ||
FramebufferUpdate::new(vec![r]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like the framebuffer-not-yet-initialized behavior, complete with white screen (or whatever Please Stand By graphics we want) should probably be centralized?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Took a gander at doing this in ddc78a6.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooops, I missed one place where the width/height was hardcoded. Let me fix in a follow up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Finished this in dbb4f6a
|
||
#[async_trait] | ||
impl Server for PropolisVncServer { | ||
async fn get_framebuffer_update(&self) -> FramebufferUpdate { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Long-term structure question: It looks like this is mostly a 'pull' model from the RFB crate? Seems like we might want at least some 'push' portions of it, like when the ramfb config is updated from inside the guest (potentially requiring an explicit change-of-res message in the proto).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's right. I structured it that way because the RFC describes the protocol as client-driven, so the server isn't supposed to send messages that aren't requested (like framebuffer updates) after the initial handshake. That said, I think where we've landed is that we're going to want to control the client for product quality purposes, so that's definitely something we can do. (It also seems to be something that the clients I've tested with might handle already -- even before I wrote code to process client messages they seemed to accept unprompted framebuffer updates, but I would need to do more testing to be sure.)
server/src/main.rs
Outdated
// XXX: vncviewer won't work without offering VncAuth, even though it doesn't ask to use | ||
// it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can probably be a "durable" (sans XXX) comment, considering the value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair. I don't think I care too much about vncviewer as a client (it seems to be buggy, or at least behaves differently from others when processing framebuffer updates), but it has the nice quality of very verbose error messages, which has helped me debug protocol errors on my end. VNCAuth isn't implemented yet (and maybe never will be) so it probably should be removed in that case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed in ddc78a6
dbb4f6a
to
a57c3ca
Compare
Summary
This PR implements prototype-level support in
propolis-server
for connecting to a propolis VM over VNC. Specifically:See the "Examples" section below for what this looks like in noVNC.
There's a lot left to implement. Broadly, this includes:
propolis-standalone
Still, I am making this PR now in the interest of merging often and making review easier as this project is ongoing and has a lot of moving parts.
Overview of Changes
rfb::server::Server
trait, which for now only requires a method to provide framebuffer data.PropolisVncServer
struct implementsrfb::server::Server
, which calls into the guest memory if the guest has been initialized (otherwise, it provides a white screen). A handle to this server is hung off the server Context that each dropshot endpoint gets. The propolisRamFb
device notifiesPropolisVncServer
of updates when it's updated viafwcfg_rw
.RamFb
entity ID through the intializer code so that its notifier function could be updated when an instance is created (instance_ensure
).server/src/main.rs
.Examples
Example Uninitialized Framebuffer (guest not started)
Here's an example of connecting without a guest running. I chose to make the screen white instead of black to differentiate between the framebuffer not being sent at all (which renders as black on some clients).

Example Initialized Framebuffer (guest started)
Here's a low-ish quality gif demonstrating what it looks like to connect to propolis-server over VNC, then create a VM and run it. (It looks better on a real client, I promise).
A couple of things to note here:
serial
command on the CLI. I'm not sure why this is, or if we should expect to see the serial console here by default (I would think so).