The generally recommended way is to include it from source files, not
headers. We had a mix of both. Let's try to be consistent and follow the
recommended way.
Add support for notifying clients about pointer movements
This change adds support for the VMware Mouse Position
pseudo-encoding[1], which is used to notify VNC clients when X11 clients
call `XWarpPointer()`[2]. This function is called by SDL (and other
similar libraries) when they detect that the server does not support
native relative motion, like some RFB clients.
With this, RFB clients can choose to adjust the local cursor position
under certain circumstances to match what the server has set. For
instance, if pointer lock has been enabled on the client's machine and
the cursor is not being drawn locally, the local position of the cursor
is irrelevant, so the RFB client can use what the server sends as the
canonical absolute position of the cursor. This ultimately enables the
possibility of games (especially FPS games) to behave how users expect
(if the clients implement the corresponding change).
Part of: #619
1: https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#vmware-cursor-position-pseudo-encoding
2: https://tronche.com/gui/x/xlib/input/XWarpPointer.html
3: https://hg.libsdl.org/SDL/file/28e3b60e2131/src/events/SDL_mouse.c#l804
We computed a safe area if a client gave us a bogus one, but we didn't
actually use it. Fix this properly and make sure we don't pass on bad
coordinates further.
Major restructuring of how streams work. Neither input nor output
streams are now blocking. This avoids stalling the rest of the client or
server when a peer is slow or unresponsive.
Note that this puts an extra burden on users of streams to make sure
they are allowed to do their work once the underlying transports are
ready (e.g. monitoring fds).
Some systems (like TLS) need to send some final data before closing
a connection. Make sure this is properly handled by cleaning up the
security object before closing the underlying network socket.
We now filter incoming data, which means we can start assuming the
clipboard data is always null terminated. This allows us to clean
up a lot of the internal handling.
This provides some basic rate limiting that will make it difficult
for an attacker to brute force passwords. Only relevant when the
blacklist is disabled as otherwise the attacker only gets a very
limited number of attempts.
Require all SMsgWriter caller to check capabilities
Make the API consisitent by requiring the caller to check what the client
supports before calling any of the write* functions. This avoids the
confusion that the functions might not always do anything.
This is what the protocol requires, rather than sending what the
client specified in the request. This should be the same in practice
except for failures and possibly some races.
We need to check earlier if we are going to send this refresh or
not. Otherwise we send out pings pointlessly, and we also stall
the request loop with a client as we clear the requested region
without actually sending an update message.
Avoid direct access to the screen dimensions and layout so that we
can make sure it stays sane. This also makes sure the layout is
properly updated when we only get the screen dimensions from the
server.
Removed the last parts of VNCSConnectionST's back door in to
VNCServerST and let the parent class fully handle coordination of
clients, and access to the desktop.
There is some client coordination needed which is better encapsulated
inside VNCServerST. This also helps hiding the desktop from the
individual clients.
Force queryConnection() to always call back to approveConnection()
rather than return special values. This makes the flow easier to
follow as it will be the same in all cases.
If we have plenty of bandwidth then CPU might be the limiting resource.
Unfortunately we don't have a good number for that limit, so add a
conservative hard coded value.
If an area recently changed then we can guess that it will most likely
change again very soon. In such a case it is meaningless to send a
lossless refresh as it will directly be overwritten. Keep track of
such areas and avoid refreshing them until we no longer see any
changes to them.
We don't want to waste bandwidth on the lossless refresh if we might
need that bandwidth for a normal update. Try to estimate how much
data we can safely send without interfering.
Resend pixel perfect copies of areas that were previously sent
using a lossy encoder. This is done when there is no normal update
to send, and no congestion.
We cannot send updates for a cursor that is outside the requested
region, so make sure we track things properly. This also has the nice
side effect of just re-sending the bits needed when the cursor overlaps
a changed part of the framebuffer.
We shouldn't unconditionally remove the server side cursor just
because the client supports client side cursors. We need to also
check that the client fulfills the other criteria for taking over
the cursor.
In most cases we will send an update at the end of processing client
messages so these extra calls only slow things down. Server initiated
events still need an explicit call though.
Improve the tracking of what cursor we've sent to the client to make
sure the initial cursor is sent properly. We previously tried to infer
this information based on if we've rendered a server side cursor or
not. This logic broke down if things triggered before we've sent the
first update to the client.
This makes it possible to create a derived class from Socket which is
not TCP based, without having VNCSConnectionST.cxx trying to call
setsockopt() on a non-socket.