The "xc" tree merged with VNC 4.1.1 code.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/branches/merge-with-vnc-4.1.1@526 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/xc/programs/Xserver/vnc/XserverDesktop.cc b/xc/programs/Xserver/vnc/XserverDesktop.cc
index f53caec..9e5ea0f 100644
--- a/xc/programs/Xserver/vnc/XserverDesktop.cc
+++ b/xc/programs/Xserver/vnc/XserverDesktop.cc
@@ -1,5 +1,5 @@
-/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
- *
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ *
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -67,6 +67,11 @@
rfb::BoolParameter alwaysSetDeferUpdateTimer("AlwaysSetDeferUpdateTimer",
"Always reset the defer update timer on every change",false);
+IntParameter queryConnectTimeout("QueryConnectTimeout",
+ "Number of seconds to show the Accept Connection dialog before "
+ "rejecting the connection",
+ 10);
+
static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col);
static rdr::U8 reverseBits[] = {
@@ -95,12 +100,14 @@
};
-class MyHTTPServer : public rfb::HTTPServer {
+class FileHTTPServer : public rfb::HTTPServer {
public:
- MyHTTPServer(XserverDesktop* d) : desktop(d) {}
- virtual ~MyHTTPServer() {}
+ FileHTTPServer(XserverDesktop* d) : desktop(d) {}
+ virtual ~FileHTTPServer() {}
- virtual rdr::InStream* getFile(const char* name, const char** contentType) {
+ virtual rdr::InStream* getFile(const char* name, const char** contentType,
+ int* contentLength, time_t* lastModified)
+ {
if (name[0] != '/' || strstr(name, "..") != 0) {
vlog.info("http request was for invalid file name");
return 0;
@@ -113,12 +120,17 @@
sprintf(fname.buf, "%s%s", httpDirStr.buf, name);
int fd = open(fname.buf, O_RDONLY);
if (fd < 0) return 0;
-
rdr::InStream* is = new rdr::FdInStream(fd, -1, 0, true);
*contentType = guessContentType(name, *contentType);
if (strlen(name) > 4 && strcasecmp(&name[strlen(name)-4], ".vnc") == 0) {
is = new rdr::SubstitutingInStream(is, desktop, 20);
*contentType = "text/html";
+ } else {
+ struct stat st;
+ if (fstat(fd, &st) == 0) {
+ *contentLength = st.st_size;
+ *lastModified = st.st_mtime;
+ }
}
return is;
}
@@ -136,8 +148,8 @@
listener(listener_), httpListener(httpListener_),
cmap(0), deferredUpdateTimerSet(false),
grabbing(false), ignoreHooks_(false), directFbptr(fbptr != 0),
- oldButtonMask(0), cursorX(0), cursorY(0),
- oldCursorX(0), oldCursorY(0)
+ oldButtonMask(0),
+ queryConnectId(0)
{
int i;
format.depth = pScreen->rootDepth;
@@ -186,9 +198,10 @@
server = new VNCServerST(name, this);
server->setPixelBuffer(this);
+ server->setQueryConnectionHandler(this);
if (httpListener)
- httpServer = new MyHTTPServer(this);
+ httpServer = new FileHTTPServer(this);
}
XserverDesktop::~XserverDesktop()
@@ -259,6 +272,24 @@
return 0;
}
+rfb::VNCServerST::queryResult
+XserverDesktop::queryConnection(network::Socket* sock,
+ const char* userName,
+ char** reason) {
+ if (queryConnectId) {
+ *reason = strDup("Another connection is currently being queried.");
+ return rfb::VNCServerST::REJECT;
+ }
+ queryConnectAddress.replaceBuf(sock->getPeerAddress());
+ if (!userName)
+ userName = "(anonymous)";
+ queryConnectUsername.replaceBuf(strDup(userName));
+ queryConnectId = sock;
+ vncQueryConnect(this, sock);
+ return rfb::VNCServerST::PENDING;
+}
+
+
void XserverDesktop::setColormap(ColormapPtr cmap_)
{
if (cmap != cmap_) {
@@ -372,7 +403,7 @@
}
server->setCursor(cursor->bits->width, cursor->bits->height,
- cursor->bits->xhot, cursor->bits->yhot,
+ Point(cursor->bits->xhot, cursor->bits->yhot),
cursorData, cursorMask);
server->tryUpdate();
delete [] cursorData;
@@ -414,6 +445,20 @@
return 0;
}
+void XserverDesktop::deferUpdate()
+{
+ if (deferUpdateTime != 0) {
+ if (!deferredUpdateTimerSet || alwaysSetDeferUpdateTimer) {
+ deferredUpdateTimerSet = true;
+ deferredUpdateTimer = TimerSet(deferredUpdateTimer, 0,
+ deferUpdateTime,
+ deferredUpdateTimerCallback, this);
+ }
+ } else {
+ server->tryUpdate();
+ }
+}
+
void XserverDesktop::add_changed(RegionPtr reg)
{
if (ignoreHooks_) return;
@@ -424,12 +469,7 @@
REGION_NUM_RECTS(reg),
(ShortRect*)REGION_RECTS(reg));
server->add_changed(rfbReg);
- if (!deferredUpdateTimerSet || alwaysSetDeferUpdateTimer) {
- deferredUpdateTimer = TimerSet(deferredUpdateTimer, 0,
- deferUpdateTime,
- deferredUpdateTimerCallback, this);
- deferredUpdateTimerSet = true;
- }
+ deferUpdate();
} catch (rdr::Exception& e) {
vlog.error("XserverDesktop::add_changed: %s",e.str());
}
@@ -445,12 +485,7 @@
REGION_NUM_RECTS(dst),
(ShortRect*)REGION_RECTS(dst));
server->add_copied(rfbReg, rfb::Point(dx, dy));
- if (!deferredUpdateTimerSet || alwaysSetDeferUpdateTimer) {
- deferredUpdateTimer = TimerSet(deferredUpdateTimer, 0,
- deferUpdateTime,
- deferredUpdateTimerCallback, this);
- deferredUpdateTimerSet = true;
- }
+ deferUpdate();
} catch (rdr::Exception& e) {
vlog.error("XserverDesktop::add_copied: %s",e.str());
}
@@ -458,11 +493,10 @@
void XserverDesktop::positionCursor()
{
- if (cursorX != oldCursorX || cursorY != oldCursorY) {
- oldCursorX = cursorX;
- oldCursorY = cursorY;
- (*pScreen->SetCursorPosition) (pScreen, cursorX, cursorY, FALSE);
- server->setCursorPos(cursorX, cursorY);
+ if (!cursorPos.equals(oldCursorPos)) {
+ oldCursorPos = cursorPos;
+ (*pScreen->SetCursorPosition) (pScreen, cursorPos.x, cursorPos.y, FALSE);
+ server->setCursorPos(cursorPos);
server->tryUpdate();
}
}
@@ -474,10 +508,9 @@
if (screenWithCursor == pScreen) {
int x, y;
GetSpritePosition(&x, &y);
- if (x != cursorX || y != cursorY) {
- cursorX = oldCursorX = x;
- cursorY = oldCursorY = y;
- server->setCursorPos(x, y);
+ if (x != cursorPos.x || y != cursorPos.y) {
+ cursorPos = oldCursorPos = Point(x, y);
+ server->setCursorPos(cursorPos);
server->tryUpdate();
}
}
@@ -491,12 +524,27 @@
server->getSockets(&sockets);
std::list<Socket*>::iterator i;
for (i = sockets.begin(); i != sockets.end(); i++) {
- FD_SET((*i)->getFd(), fds);
+ int fd = (*i)->getFd();
+ if ((*i)->isShutdown()) {
+ vlog.debug("client gone, sock %d",fd);
+ server->removeSocket(*i);
+ vncClientGone(fd);
+ delete (*i);
+ } else {
+ FD_SET(fd, fds);
+ }
}
if (httpServer) {
httpServer->getSockets(&sockets);
for (i = sockets.begin(); i != sockets.end(); i++) {
- FD_SET((*i)->getFd(), fds);
+ int fd = (*i)->getFd();
+ if ((*i)->isShutdown()) {
+ vlog.debug("http client gone, sock %d",fd);
+ httpServer->removeSocket(*i);
+ delete (*i);
+ } else {
+ FD_SET(fd, fds);
+ }
}
}
} catch (rdr::Exception& e) {
@@ -517,7 +565,7 @@
if (FD_ISSET(listener->getFd(), fds)) {
FD_CLR(listener->getFd(), fds);
Socket* sock = listener->accept();
- server->addClient(sock);
+ server->addSocket(sock);
vlog.debug("new client, sock %d",sock->getFd());
}
}
@@ -526,7 +574,7 @@
if (FD_ISSET(httpListener->getFd(), fds)) {
FD_CLR(httpListener->getFd(), fds);
Socket* sock = httpListener->accept();
- httpServer->addClient(sock);
+ httpServer->addSocket(sock);
vlog.debug("new http client, sock %d",sock->getFd());
}
}
@@ -538,10 +586,7 @@
int fd = (*i)->getFd();
if (FD_ISSET(fd, fds)) {
FD_CLR(fd, fds);
- if (!server->processSocketEvent(*i)) {
- vlog.debug("client gone, sock %d",fd);
- vncClientGone(fd);
- }
+ server->processSocketEvent(*i);
}
}
@@ -551,9 +596,7 @@
int fd = (*i)->getFd();
if (FD_ISSET(fd, fds)) {
FD_CLR(fd, fds);
- if (!httpServer->processSocketEvent(*i)) {
- vlog.debug("http client gone, sock %d",fd);
- }
+ httpServer->processSocketEvent(*i);
}
}
}
@@ -576,7 +619,7 @@
void XserverDesktop::addClient(Socket* sock, bool reverse)
{
vlog.debug("new client, sock %d reverse %d",sock->getFd(),reverse);
- server->addClient(sock, reverse);
+ server->addSocket(sock, reverse);
}
void XserverDesktop::disconnectClients()
@@ -586,12 +629,36 @@
}
+int XserverDesktop::getQueryTimeout(void* opaqueId,
+ const char** address,
+ const char** username)
+{
+ if (opaqueId && queryConnectId == opaqueId) {
+ vlog.info("address=%s, username=%s, timeout=%d",
+ queryConnectAddress.buf, queryConnectUsername.buf,
+ (int)queryConnectTimeout);
+ if (address) *address = queryConnectAddress.buf;
+ if (username) *username = queryConnectUsername.buf;
+ return queryConnectTimeout;
+ }
+ return 0;
+}
+
+void XserverDesktop::approveConnection(void* opaqueId, bool accept,
+ const char* rejectMsg)
+{
+ if (queryConnectId == opaqueId) {
+ server->approveConnection((network::Socket*)opaqueId, accept, rejectMsg);
+ queryConnectId = 0;
+ }
+}
+
///////////////////////////////////////////////////////////////////////////
//
// SDesktop callbacks
-void XserverDesktop::pointerEvent(const Point& pos, rdr::U8 buttonMask)
+void XserverDesktop::pointerEvent(const Point& pos, int buttonMask)
{
xEvent ev;
DevicePtr dev = LookupPointerDevice();
@@ -609,7 +676,7 @@
ev.u.keyButtonPointer.rootY = pos.y;
ev.u.keyButtonPointer.time = GetTimeInMillis();
- if (pos.x != cursorX || pos.y != cursorY)
+ if (!pos.equals(cursorPos))
(*dev->processInputProc)(&ev, (DeviceIntPtr)dev, 1);
for (int i = 0; i < 5; i++) {
@@ -622,8 +689,7 @@
}
}
- cursorX = pos.x;
- cursorY = pos.y;
+ cursorPos = pos;
oldButtonMask = buttonMask;
}
@@ -662,16 +728,23 @@
void XserverDesktop::lookup(int index, int* r, int* g, int* b)
{
- EntryPtr pent;
- pent = (EntryPtr)&cmap->red[index];
- if (pent->fShared) {
- *r = pent->co.shco.red->color;
- *g = pent->co.shco.green->color;
- *b = pent->co.shco.blue->color;
+ if ((cmap->c_class | DynamicClass) == DirectColor) {
+ VisualPtr v = cmap->pVisual;
+ *r = cmap->red [(index & v->redMask ) >> v->offsetRed ].co.local.red;
+ *g = cmap->green[(index & v->greenMask) >> v->offsetGreen].co.local.green;
+ *b = cmap->blue [(index & v->blueMask ) >> v->offsetBlue ].co.local.blue;
} else {
- *r = pent->co.local.red;
- *g = pent->co.local.green;
- *b = pent->co.local.blue;
+ EntryPtr pent;
+ pent = (EntryPtr)&cmap->red[index];
+ if (pent->fShared) {
+ *r = pent->co.shco.red->color;
+ *g = pent->co.shco.green->color;
+ *b = pent->co.shco.blue->color;
+ } else {
+ *r = pent->co.local.red;
+ *g = pent->co.local.green;
+ *b = pent->co.local.blue;
+ }
}
}