diff options
author | Adam Tkac <atkac@redhat.com> | 2008-03-21 18:56:48 +0000 |
---|---|---|
committer | Adam Tkac <atkac@redhat.com> | 2008-03-21 18:56:48 +0000 |
commit | 4c0427ffb370b5020a6f82456106774b6711ddd4 (patch) | |
tree | 20e0eb1d073746e04d953b488618573de14abbf6 /unix/xserver/hw/vnc/vncExtInit.cc | |
parent | bee114ae5e69b10e132c5d6d680045d9165e5a90 (diff) | |
download | tigervnc-4c0427ffb370b5020a6f82456106774b6711ddd4.tar.gz tigervnc-4c0427ffb370b5020a6f82456106774b6711ddd4.zip |
- moved Xvnc sources to unix/xserver/hw/vnc directory to affect current X tree
- replaced unix/xc.patch by unix/xserver.patch
- completely deleted unneded unix/xc subtree (sources are in unix/xserver/hw/vnc)
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/branches/1.5-xserver@2439 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'unix/xserver/hw/vnc/vncExtInit.cc')
-rw-r--r-- | unix/xserver/hw/vnc/vncExtInit.cc | 866 |
1 files changed, 866 insertions, 0 deletions
diff --git a/unix/xserver/hw/vnc/vncExtInit.cc b/unix/xserver/hw/vnc/vncExtInit.cc new file mode 100644 index 00000000..9cf9d21b --- /dev/null +++ b/unix/xserver/hw/vnc/vncExtInit.cc @@ -0,0 +1,866 @@ +/* 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 + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include <stdio.h> + +extern "C" { +#define class c_class +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "scrnintstr.h" +#include "selection.h" +#define _VNCEXT_SERVER_ +#define _VNCEXT_PROTO_ +#include "vncExt.h" +#undef class +#undef xalloc +} + +#include <rfb/Configuration.h> +#include <rfb/Logger_stdio.h> +#include <rfb/LogWriter.h> +#include <rfb/util.h> +#include <rfb/ServerCore.h> +#include <rfb/SSecurityFactoryStandard.h> +#include <rdr/HexOutStream.h> +#include <rfb/LogWriter.h> +#undef max +#undef min +#include <network/TcpSocket.h> + +#include "XserverDesktop.h" +#include "vncHooks.h" +#include "vncExtInit.h" + +extern "C" { + + extern void vncExtensionInit(); + static void vncResetProc(ExtensionEntry* extEntry); + static void vncBlockHandler(pointer data, OSTimePtr t, pointer readmask); + static void vncWakeupHandler(pointer data, int nfds, pointer readmask); + static void vncClientStateChange(CallbackListPtr*, pointer, pointer); + static void SendSelectionChangeEvent(Atom selection); + static int ProcVncExtDispatch(ClientPtr client); + static int SProcVncExtDispatch(ClientPtr client); + + extern char *display; + + extern Selection *CurrentSelections; + extern int NumCurrentSelections; +} + +using namespace rfb; + +static rfb::LogWriter vlog("vncext"); + +static unsigned long vncExtGeneration = 0; +static bool initialised = false; +static XserverDesktop* desktop[MAXSCREENS] = { 0, }; +void* vncFbptr[MAXSCREENS] = { 0, }; + +static char* clientCutText = 0; +static int clientCutTextLen = 0; + +static XserverDesktop* queryConnectDesktop = 0; +static void* queryConnectId = 0; +static int queryConnectTimeout = 0; +static OsTimerPtr queryConnectTimer = 0; + +static struct VncInputSelect* vncInputSelectHead = 0; +struct VncInputSelect { + VncInputSelect(ClientPtr c, Window w, int m) : client(c), window(w), mask(m) + { + next = vncInputSelectHead; + vncInputSelectHead = this; + } + ClientPtr client; + Window window; + int mask; + VncInputSelect* next; +}; + +static int nPrevSelections = 0; +static TimeStamp* prevSelectionTimes = 0; + +static int vncErrorBase = 0; +static int vncEventBase = 0; +static char* vncPasswdFile = 0; +int vncInetdSock = -1; + +rfb::AliasParameter rfbauth("rfbauth", "Alias for PasswordFile", + &SSecurityFactoryStandard::vncAuthPasswdFile); +rfb::StringParameter httpDir("httpd", + "Directory containing files to serve via HTTP", + ""); +rfb::IntParameter httpPort("httpPort", "TCP port to listen for HTTP",0); +rfb::AliasParameter rfbwait("rfbwait", "Alias for ClientWaitTimeMillis", + &rfb::Server::clientWaitTimeMillis); +rfb::IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",0); +rfb::StringParameter desktopName("desktop", "Name of VNC desktop","x11"); +rfb::BoolParameter localhostOnly("localhost", + "Only allow connections from localhost", + false); + +void vncExtensionInit() +{ + if (vncExtGeneration == serverGeneration) { + vlog.error("vncExtensionInit: called twice in same generation?"); + return; + } + vncExtGeneration = serverGeneration; + + ExtensionEntry* extEntry + = AddExtension(VNCEXTNAME, VncExtNumberEvents, VncExtNumberErrors, + ProcVncExtDispatch, SProcVncExtDispatch, vncResetProc, + StandardMinorOpcode); + if (!extEntry) { + ErrorF("vncExtInit: AddExtension failed\n"); + return; + } + + vncErrorBase = extEntry->errorBase; + vncEventBase = extEntry->eventBase; + + vlog.info("VNC extension running!"); + + if (!AddCallback(&ClientStateCallback, vncClientStateChange, 0)) { + FatalError("AddCallback failed\n"); + } + + try { + if (!initialised) { + rfb::initStdIOLoggers(); + initialised = true; + } + + for (int scr = 0; scr < screenInfo.numScreens; scr++) { + + if (!desktop[scr]) { + network::TcpListener* listener = 0; + network::TcpListener* httpListener = 0; + if (scr == 0 && vncInetdSock != -1) { + if (network::TcpSocket::isSocket(vncInetdSock) && + !network::TcpSocket::isConnected(vncInetdSock)) + { + listener = new network::TcpListener(0, 0, vncInetdSock, true); + vlog.info("inetd wait"); + } + } else { + int port = rfbport; + if (port == 0) port = 5900 + atoi(display); + port += 1000 * scr; + listener = new network::TcpListener(port, localhostOnly); + vlog.info("Listening for VNC connections on port %d",port); + CharArray httpDirStr(httpDir.getData()); + if (httpDirStr.buf[0]) { + port = httpPort; + if (port == 0) port = 5800 + atoi(display); + port += 1000 * scr; + httpListener = new network::TcpListener(port, localhostOnly); + vlog.info("Listening for HTTP connections on port %d",port); + } + } + + CharArray desktopNameStr(desktopName.getData()); + desktop[scr] = new XserverDesktop(screenInfo.screens[scr], listener, + httpListener, + desktopNameStr.buf, + vncFbptr[scr]); + vlog.info("created VNC server for screen %d", scr); + + if (scr == 0 && vncInetdSock != -1 && !listener) { + network::Socket* sock = new network::TcpSocket(vncInetdSock); + desktop[scr]->addClient(sock, false); + vlog.info("added inetd sock"); + } + + } else { + desktop[scr]->serverReset(screenInfo.screens[scr]); + } + + vncHooksInit(screenInfo.screens[scr], desktop[scr]); + } + + RegisterBlockAndWakeupHandlers(vncBlockHandler, vncWakeupHandler, 0); + + } catch (rdr::Exception& e) { + vlog.error("vncExtInit: %s",e.str()); + } +} + +static void vncResetProc(ExtensionEntry* extEntry) +{ +} + +// +// vncBlockHandler - called just before the X server goes into select(). Call +// on to the block handler for each desktop. Then check whether any of the +// selections have changed, and if so, notify any interested X clients. +// + +static void vncBlockHandler(pointer data, OSTimePtr timeout, pointer readmask) +{ + fd_set* fds = (fd_set*)readmask; + + for (int scr = 0; scr < screenInfo.numScreens; scr++) { + if (desktop[scr]) { + desktop[scr]->blockHandler(fds); + } + } + + if (nPrevSelections != NumCurrentSelections) { + prevSelectionTimes + = (TimeStamp*)xnfrealloc(prevSelectionTimes, + NumCurrentSelections * sizeof(TimeStamp)); + for (int i = nPrevSelections; i < NumCurrentSelections; i++) { + prevSelectionTimes[i].months = 0; + prevSelectionTimes[i].milliseconds = 0; + } + nPrevSelections = NumCurrentSelections; + } + for (int i = 0; i < NumCurrentSelections; i++) { + if (CurrentSelections[i].lastTimeChanged.months + != prevSelectionTimes[i].months || + CurrentSelections[i].lastTimeChanged.milliseconds + != prevSelectionTimes[i].milliseconds) + { + SendSelectionChangeEvent(CurrentSelections[i].selection); + prevSelectionTimes[i] = CurrentSelections[i].lastTimeChanged; + } + } +} + +static void vncWakeupHandler(pointer data, int nfds, pointer readmask) +{ + fd_set* fds = (fd_set*)readmask; + + for (int scr = 0; scr < screenInfo.numScreens; scr++) { + if (desktop[scr]) { + desktop[scr]->wakeupHandler(fds, nfds); + } + } +} + +static void vncClientStateChange(CallbackListPtr*, pointer, pointer p) +{ + ClientPtr client = ((NewClientInfoRec*)p)->client; + if (client->clientState == ClientStateGone) { + VncInputSelect** nextPtr = &vncInputSelectHead; + for (VncInputSelect* cur = vncInputSelectHead; cur; cur = *nextPtr) { + if (cur->client == client) { + *nextPtr = cur->next; + delete cur; + continue; + } + nextPtr = &cur->next; + } + } +} + +void vncBell() +{ + for (int scr = 0; scr < screenInfo.numScreens; scr++) { + if (desktop[scr]) { + desktop[scr]->bell(); + } + } +} + +void vncClientGone(int fd) +{ + if (fd == vncInetdSock) { + fprintf(stderr,"inetdSock client gone\n"); + GiveUp(0); + } +} + +void vncClientCutText(const char* str, int len) +{ + delete [] clientCutText; + clientCutText = new char[len]; + memcpy(clientCutText, str, len); + clientCutTextLen = len; + xVncExtClientCutTextNotifyEvent ev; + ev.type = vncEventBase + VncExtClientCutTextNotify; + for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) { + if (cur->mask & VncExtClientCutTextMask) { + ev.sequenceNumber = cur->client->sequence; + ev.window = cur->window; + ev.time = GetTimeInMillis(); + if (cur->client->swapped) { + int n; + swaps(&ev.sequenceNumber, n); + swapl(&ev.window, n); + swapl(&ev.time, n); + } + WriteToClient(cur->client, sizeof(xVncExtClientCutTextNotifyEvent), + (char *)&ev); + } + } +} + + +static CARD32 queryConnectTimerCallback(OsTimerPtr timer, + CARD32 now, pointer arg) +{ + if (queryConnectTimeout) + queryConnectDesktop->approveConnection(queryConnectId, false, "The attempt to prompt the user to accept the connection failed"); + // Re-notify clients, causing them to discover that we're done + vncQueryConnect(queryConnectDesktop, queryConnectId); + return 0; +} + +void vncQueryConnect(XserverDesktop* desktop, void* opaqueId) +{ + // Only one query can be processed at any one time + if (queryConnectTimeout && ((desktop != queryConnectDesktop) || + (opaqueId != queryConnectId))) { + desktop->approveConnection(opaqueId, false, + "Another connection is currently being queried."); + return; + } + + // Get the query timeout. If it's zero, there is no query. + queryConnectTimeout = desktop->getQueryTimeout(opaqueId); + queryConnectId = queryConnectTimeout ? opaqueId : 0; + queryConnectDesktop = queryConnectTimeout ? desktop : 0; + + // Notify clients + bool notified = false; + xVncExtQueryConnectNotifyEvent ev; + ev.type = vncEventBase + VncExtQueryConnectNotify; + for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) { + if (cur->mask & VncExtQueryConnectMask) { + ev.sequenceNumber = cur->client->sequence; + ev.window = cur->window; + if (cur->client->swapped) { + int n; + swaps(&ev.sequenceNumber, n); + swapl(&ev.window, n); + } + WriteToClient(cur->client, sizeof(xVncExtQueryConnectNotifyEvent), + (char *)&ev); + notified = true; + } + } + + // If we're being asked to query a connection (rather than to cancel + // a query), and haven't been able to notify clients then reject it. + if (queryConnectTimeout && !notified) { + queryConnectTimeout = 0; + queryConnectId = 0; + queryConnectDesktop = 0; + desktop->approveConnection(opaqueId, false, + "Unable to query the local user to accept the connection."); + return; + } + + // Set a timer so that if no-one ever responds, we will eventually + // reject the connection + // NB: We don't set a timer if sock is null, since that indicates + // that pending queries should be cancelled. + if (queryConnectDesktop) + queryConnectTimer = TimerSet(queryConnectTimer, 0, + queryConnectTimeout*2000, + queryConnectTimerCallback, 0); + else + TimerCancel(queryConnectTimer); +} + +static void SendSelectionChangeEvent(Atom selection) +{ + xVncExtSelectionChangeNotifyEvent ev; + ev.type = vncEventBase + VncExtSelectionChangeNotify; + for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) { + if (cur->mask & VncExtSelectionChangeMask) { + ev.sequenceNumber = cur->client->sequence; + ev.window = cur->window; + ev.selection = selection; + if (cur->client->swapped) { + int n; + swaps(&ev.sequenceNumber, n); + swapl(&ev.window, n); + swapl(&ev.selection, n); + } + WriteToClient(cur->client, sizeof(xVncExtSelectionChangeNotifyEvent), + (char *)&ev); + } + } +} + +static int ProcVncExtSetParam(ClientPtr client) +{ + REQUEST(xVncExtSetParamReq); + REQUEST_FIXED_SIZE(xVncExtSetParamReq, stuff->paramLen); + CharArray param(stuff->paramLen+1); + strncpy(param.buf, (char*)&stuff[1], stuff->paramLen); + param.buf[stuff->paramLen] = 0; + + xVncExtSetParamReply rep; + int n; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.success = rfb::Configuration::setParam(param.buf); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof(xVncExtSetParamReply), (char *)&rep); + return (client->noClientException); +} + +static int SProcVncExtSetParam(ClientPtr client) +{ + register char n; + REQUEST(xVncExtSetParamReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xVncExtSetParamReq); + return ProcVncExtSetParam(client); +} + +static int ProcVncExtGetParam(ClientPtr client) +{ + REQUEST(xVncExtGetParamReq); + REQUEST_FIXED_SIZE(xVncExtGetParamReq, stuff->paramLen); + CharArray param(stuff->paramLen+1); + strncpy(param.buf, (char*)&stuff[1], stuff->paramLen); + param.buf[stuff->paramLen] = 0; + + xVncExtGetParamReply rep; + int n; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.success = 0; + int len = 0; + char* value = 0; + rfb::VoidParameter* p = rfb::Configuration::getParam(param.buf); + // Hack to avoid exposing password! + if (strcasecmp(param.buf, "Password") == 0) + p = 0; + if (p) { + value = p->getValueStr(); + rep.success = 1; + len = value ? strlen(value) : 0; + } + rep.length = (len + 3) >> 2; + rep.valueLen = len; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.valueLen, n); + } + WriteToClient(client, sizeof(xVncExtGetParamReply), (char *)&rep); + if (value) + WriteToClient(client, len, value); + delete [] value; + return (client->noClientException); +} + +static int SProcVncExtGetParam(ClientPtr client) +{ + register char n; + REQUEST(xVncExtGetParamReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xVncExtGetParamReq); + return ProcVncExtGetParam(client); +} + +static int ProcVncExtGetParamDesc(ClientPtr client) +{ + REQUEST(xVncExtGetParamDescReq); + REQUEST_FIXED_SIZE(xVncExtGetParamDescReq, stuff->paramLen); + CharArray param(stuff->paramLen+1); + strncpy(param.buf, (char*)&stuff[1], stuff->paramLen); + param.buf[stuff->paramLen] = 0; + + xVncExtGetParamDescReply rep; + int n; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.success = 0; + int len = 0; + const char* desc = 0; + rfb::VoidParameter* p = rfb::Configuration::getParam(param.buf); + if (p) { + desc = p->getDescription(); + rep.success = 1; + len = desc ? strlen(desc) : 0; + } + rep.length = (len + 3) >> 2; + rep.descLen = len; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.descLen, n); + } + WriteToClient(client, sizeof(xVncExtGetParamDescReply), (char *)&rep); + if (desc) + WriteToClient(client, len, (char*)desc); + return (client->noClientException); +} + +static int SProcVncExtGetParamDesc(ClientPtr client) +{ + register char n; + REQUEST(xVncExtGetParamDescReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xVncExtGetParamDescReq); + return ProcVncExtGetParamDesc(client); +} + +static int ProcVncExtListParams(ClientPtr client) +{ + REQUEST(xVncExtListParamsReq); + REQUEST_SIZE_MATCH(xVncExtListParamsReq); + + xVncExtListParamsReply rep; + int n; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + + int nParams = 0; + int len = 0; + for (ParameterIterator i(Configuration::global()); i.param; i.next()) { + int l = strlen(i.param->getName()); + if (l <= 255) { + nParams++; + len += l + 1; + } + } + rep.length = (len + 3) >> 2; + rep.nParams = nParams; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.nParams, n); + } + WriteToClient(client, sizeof(xVncExtListParamsReply), (char *)&rep); + rdr::U8* data = new rdr::U8[len]; + rdr::U8* ptr = data; + for (ParameterIterator i(Configuration::global()); i.param; i.next()) { + int l = strlen(i.param->getName()); + if (l <= 255) { + *ptr++ = l; + memcpy(ptr, i.param->getName(), l); + ptr += l; + } + } + WriteToClient(client, len, (char*)data); + delete [] data; + return (client->noClientException); +} + +static int SProcVncExtListParams(ClientPtr client) +{ + register char n; + REQUEST(xVncExtListParamsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xVncExtListParamsReq); + return ProcVncExtListParams(client); +} + +static int ProcVncExtSetServerCutText(ClientPtr client) +{ + REQUEST(xVncExtSetServerCutTextReq); + REQUEST_FIXED_SIZE(xVncExtSetServerCutTextReq, stuff->textLen); + char* str = new char[stuff->textLen+1]; + strncpy(str, (char*)&stuff[1], stuff->textLen); + str[stuff->textLen] = 0; + for (int scr = 0; scr < screenInfo.numScreens; scr++) { + if (desktop[scr]) { + desktop[scr]->serverCutText(str, stuff->textLen); + } + } + delete [] str; + return (client->noClientException); +} + +static int SProcVncExtSetServerCutText(ClientPtr client) +{ + register char n; + REQUEST(xVncExtSetServerCutTextReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xVncExtSetServerCutTextReq); + swapl(&stuff->textLen, n); + return ProcVncExtSetServerCutText(client); +} + +static int ProcVncExtGetClientCutText(ClientPtr client) +{ + REQUEST(xVncExtGetClientCutTextReq); + REQUEST_SIZE_MATCH(xVncExtGetClientCutTextReq); + + xVncExtGetClientCutTextReply rep; + int n; + rep.type = X_Reply; + rep.length = (clientCutTextLen + 3) >> 2; + rep.sequenceNumber = client->sequence; + rep.textLen = clientCutTextLen; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.textLen, n); + } + WriteToClient(client, sizeof(xVncExtGetClientCutTextReply), (char *)&rep); + if (clientCutText) + WriteToClient(client, clientCutTextLen, clientCutText); + return (client->noClientException); +} + +static int SProcVncExtGetClientCutText(ClientPtr client) +{ + register char n; + REQUEST(xVncExtGetClientCutTextReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xVncExtGetClientCutTextReq); + return ProcVncExtGetClientCutText(client); +} + +static int ProcVncExtSelectInput(ClientPtr client) +{ + REQUEST(xVncExtSelectInputReq); + REQUEST_SIZE_MATCH(xVncExtSelectInputReq); + VncInputSelect** nextPtr = &vncInputSelectHead; + VncInputSelect* cur; + for (cur = vncInputSelectHead; cur; cur = *nextPtr) { + if (cur->client == client && cur->window == stuff->window) { + cur->mask = stuff->mask; + if (!cur->mask) { + *nextPtr = cur->next; + delete cur; + } + break; + } + nextPtr = &cur->next; + } + if (!cur) { + cur = new VncInputSelect(client, stuff->window, stuff->mask); + } + return (client->noClientException); +} + +static int SProcVncExtSelectInput(ClientPtr client) +{ + register char n; + REQUEST(xVncExtSelectInputReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xVncExtSelectInputReq); + swapl(&stuff->window, n); + swapl(&stuff->mask, n); + return ProcVncExtSelectInput(client); +} + +static int ProcVncExtConnect(ClientPtr client) +{ + REQUEST(xVncExtConnectReq); + REQUEST_FIXED_SIZE(xVncExtConnectReq, stuff->strLen); + CharArray str(stuff->strLen+1); + strncpy(str.buf, (char*)&stuff[1], stuff->strLen); + str.buf[stuff->strLen] = 0; + + xVncExtConnectReply rep; + rep.success = 0; + if (desktop[0]) { + if (stuff->strLen == 0) { + try { + desktop[0]->disconnectClients(); + rep.success = 1; + } catch (rdr::Exception& e) { + vlog.error("Disconnecting all clients: %s",e.str()); + } + } else { + int port = 5500; + for (int i = 0; i < stuff->strLen; i++) { + if (str.buf[i] == ':') { + port = atoi(&str.buf[i+1]); + str.buf[i] = 0; + break; + } + } + + try { + network::Socket* sock = new network::TcpSocket(str.buf, port); + desktop[0]->addClient(sock, true); + rep.success = 1; + } catch (rdr::Exception& e) { + vlog.error("Reverse connection: %s",e.str()); + } + } + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (client->swapped) { + int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof(xVncExtConnectReply), (char *)&rep); + return (client->noClientException); +} + +static int SProcVncExtConnect(ClientPtr client) +{ + register char n; + REQUEST(xVncExtConnectReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xVncExtConnectReq); + return ProcVncExtConnect(client); +} + + +static int ProcVncExtGetQueryConnect(ClientPtr client) +{ + REQUEST(xVncExtGetQueryConnectReq); + REQUEST_SIZE_MATCH(xVncExtGetQueryConnectReq); + + const char *qcAddress=0, *qcUsername=0; + int qcTimeout; + if (queryConnectDesktop) + qcTimeout = queryConnectDesktop->getQueryTimeout(queryConnectId, + &qcAddress, &qcUsername); + else + qcTimeout = 0; + + xVncExtGetQueryConnectReply rep; + int n; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.timeout = qcTimeout; + rep.addrLen = qcTimeout ? strlen(qcAddress) : 0; + rep.userLen = qcTimeout ? strlen(qcUsername) : 0; + rep.opaqueId = (CARD32)queryConnectId; + rep.length = (rep.userLen + rep.addrLen + 3) >> 2; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.userLen, n); + swapl(&rep.addrLen, n); + swapl(&rep.timeout, n); + swapl(&rep.opaqueId, n); + } + WriteToClient(client, sizeof(xVncExtGetQueryConnectReply), (char *)&rep); + if (qcTimeout) + WriteToClient(client, strlen(qcAddress), (char*)qcAddress); + if (qcTimeout) + WriteToClient(client, strlen(qcUsername), (char*)qcUsername); + return (client->noClientException); +} + +static int SProcVncExtGetQueryConnect(ClientPtr client) +{ + register char n; + REQUEST(xVncExtGetQueryConnectReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xVncExtGetQueryConnectReq); + return ProcVncExtGetQueryConnect(client); +} + + +static int ProcVncExtApproveConnect(ClientPtr client) +{ + REQUEST(xVncExtApproveConnectReq); + REQUEST_SIZE_MATCH(xVncExtApproveConnectReq); + if (queryConnectId == (void*)stuff->opaqueId) { + for (int scr = 0; scr < screenInfo.numScreens; scr++) { + if (desktop[scr]) { + desktop[scr]->approveConnection(queryConnectId, stuff->approve, + "Connection rejected by local user"); + } + } + // Inform other clients of the event and tidy up + vncQueryConnect(queryConnectDesktop, queryConnectId); + } + return (client->noClientException); +} + +static int SProcVncExtApproveConnect(ClientPtr client) +{ + register char n; + REQUEST(xVncExtApproveConnectReq); + swaps(&stuff->length, n); + swapl(&stuff->opaqueId, n); + REQUEST_SIZE_MATCH(xVncExtApproveConnectReq); + return ProcVncExtApproveConnect(client); +} + + +static int ProcVncExtDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_VncExtSetParam: + return ProcVncExtSetParam(client); + case X_VncExtGetParam: + return ProcVncExtGetParam(client); + case X_VncExtGetParamDesc: + return ProcVncExtGetParamDesc(client); + case X_VncExtListParams: + return ProcVncExtListParams(client); + case X_VncExtSetServerCutText: + return ProcVncExtSetServerCutText(client); + case X_VncExtGetClientCutText: + return ProcVncExtGetClientCutText(client); + case X_VncExtSelectInput: + return ProcVncExtSelectInput(client); + case X_VncExtConnect: + return ProcVncExtConnect(client); + case X_VncExtGetQueryConnect: + return ProcVncExtGetQueryConnect(client); + case X_VncExtApproveConnect: + return ProcVncExtApproveConnect(client); + default: + return BadRequest; + } +} + +static int SProcVncExtDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_VncExtSetParam: + return SProcVncExtSetParam(client); + case X_VncExtGetParam: + return SProcVncExtGetParam(client); + case X_VncExtGetParamDesc: + return SProcVncExtGetParamDesc(client); + case X_VncExtListParams: + return SProcVncExtListParams(client); + case X_VncExtSetServerCutText: + return SProcVncExtSetServerCutText(client); + case X_VncExtGetClientCutText: + return SProcVncExtGetClientCutText(client); + case X_VncExtSelectInput: + return SProcVncExtSelectInput(client); + case X_VncExtConnect: + return SProcVncExtConnect(client); + case X_VncExtGetQueryConnect: + return SProcVncExtGetQueryConnect(client); + case X_VncExtApproveConnect: + return SProcVncExtApproveConnect(client); + default: + return BadRequest; + } +} + |