vncServer.cpp
资源名称:vnc3326s.zip [点击查看]
上传用户:sbftbdw
上传日期:2007-01-03
资源大小:379k
文件大小:20k
源码类别:
远程控制编程
开发平台:
Visual C++
- // Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory
- //
- // This file is part of the VNC system.
- //
- // The VNC system 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 program 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 program; if not, write to the Free Software
- // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- // USA.
- //
- // If the source code for the VNC system is not available from the place
- // whence you received this file, check http://www.orl.co.uk/vnc or contact
- // the authors on vnc@orl.co.uk for information on obtaining it.
- // vncServer.cpp
- // vncServer class implementation
- // Includes
- #include "stdhdrs.h"
- #include <omnithread.h>
- #include <string.h>
- #include <lmcons.h>
- // Custom
- #include "WinVNC.h"
- #include "vncServer.h"
- #include "vncSockConnect.h"
- #include "vncCorbaConnect.h"
- #include "vncClient.h"
- #include "vncService.h"
- // Constructor/destructor
- vncServer::vncServer()
- {
- // Initialise some important stuffs...
- m_socketConn = NULL;
- m_corbaConn = NULL;
- m_httpConn = NULL;
- m_desktop = NULL;
- m_name = NULL;
- m_port = DISPLAY_TO_PORT(0);
- m_autoportselect = TRUE;
- m_passwd_required = TRUE;
- {
- vncPasswd::FromClear clearPWD;
- memcpy(m_password, clearPWD, MAXPWLEN);
- }
- // Autolock settings
- m_lock_on_exit = 0;
- // Set the polling mode options
- m_poll_fullscreen = FALSE;
- m_poll_foreground = FALSE;
- m_poll_undercursor = TRUE;
- m_poll_oneventonly = FALSE;
- m_poll_consoleonly = TRUE;
- // General options
- m_loopback_allowed = FALSE;
- m_lock_on_exit = 0;
- m_connect_pri = 0;
- // Set the remote input options
- m_enable_inputs = TRUE;
- // Clear the client mapping table
- for (int x=0; x<MAX_CLIENTS; x++)
- m_clientmap[x] = NULL;
- m_nextid = 0;
- // Signal set when a client quits
- m_clientquitsig = new omni_condition(&m_clientsLock);
- }
- vncServer::~vncServer()
- {
- log.Print(LL_STATE, VNCLOG("shutting down server objectn"));
- // If there is a socket_conn object then delete it
- if (m_socketConn != NULL)
- {
- delete m_socketConn;
- m_socketConn = NULL;
- }
- if (m_corbaConn != NULL)
- {
- delete m_corbaConn;
- m_corbaConn = NULL;
- }
- if (m_httpConn != NULL)
- {
- delete m_httpConn;
- m_httpConn = NULL;
- }
- // Remove any active clients!
- KillAll();
- // Wait for all the clients to die
- WaitUntilAuthEmpty();
- // Don't free the desktop until no KillClient is likely to free it
- { omni_mutex_lock l(m_desktopLock);
- if (m_desktop != NULL)
- {
- delete m_desktop;
- m_desktop = NULL;
- }
- }
- if (m_name != NULL)
- {
- free(m_name);
- m_name = NULL;
- }
- if (m_clientquitsig != NULL)
- {
- delete m_clientquitsig;
- m_clientquitsig = NULL;
- }
- }
- // Client handling functions
- vncClientId
- vncServer::AddClient(VSocket *socket, BOOL auth)
- {
- return AddClient(socket, auth, FALSE, 0, TRUE, TRUE);
- }
- vncClientId
- vncServer::AddClient(VSocket *socket, BOOL auth,
- BOOL teleport, int capability,
- BOOL keysenabled, BOOL ptrenabled)
- {
- vncClient *client;
- omni_mutex_lock l(m_clientsLock);
- // Try to allocate a client id...
- vncClientId clientid = m_nextid;
- do
- {
- clientid = (clientid+1) % MAX_CLIENTS;
- if (clientid == m_nextid)
- {
- return -1;
- }
- }
- while (m_clientmap[clientid] != NULL);
- // Create a new client and add it to the relevant client list
- client = new vncClient();
- if (client == NULL)
- return -1;
- if (!client->Init(this, socket, auth, clientid))
- {
- // The client will delete the socket for us...
- log.Print(LL_CONNERR, VNCLOG("failed to initialise client objectn"));
- delete client;
- return -1;
- }
- // Set the client's settings
- client->SetTeleport(teleport);
- client->SetCapability(capability);
- client->EnableKeyboard(keysenabled && m_enable_inputs);
- client->EnablePointer(ptrenabled && m_enable_inputs);
- m_clientmap[clientid] = client;
- // Add the client to unauth the client list
- m_unauthClients.push_back(clientid);
- // Notify anyone interested about this event
- DoNotify(WM_SRV_CLIENT_CONNECT, 0, 0);
- log.Print(LL_INTINFO, VNCLOG("AddClient() donen"));
- return clientid;
- }
- BOOL
- vncServer::Authenticated(vncClientId clientid)
- {
- vncClientList::iterator i;
- BOOL authok = TRUE;
- omni_mutex_lock l1(m_desktopLock);
- omni_mutex_lock l2(m_clientsLock);
- // Search the unauthenticated client list
- for (i = m_unauthClients.begin(); i != m_unauthClients.end(); i++)
- {
- // Is this the right client?
- if ((*i) == clientid)
- {
- vncClient *client = GetClient(clientid);
- // Yes, so remove the client and add it to the auth list
- m_unauthClients.erase(i);
- // Create the screen handler if necessary
- if (m_desktop == NULL)
- {
- m_desktop = new vncDesktop();
- if (m_desktop == NULL)
- {
- client->Kill();
- authok = FALSE;
- break;
- }
- if (!m_desktop->Init(this))
- {
- client->Kill();
- authok = FALSE;
- delete m_desktop;
- m_desktop = NULL;
- break;
- }
- }
- // Create a buffer object for this client
- vncBuffer *buffer = new vncBuffer(m_desktop);
- if (buffer == NULL)
- {
- client->Kill();
- authok = FALSE;
- break;
- }
- // Tell the client about this new buffer
- client->SetBuffer(buffer);
- // Add the client to the auth list
- m_authClients.push_back(clientid);
- break;
- }
- }
- // Notify anyone interested of this event
- DoNotify(WM_SRV_CLIENT_AUTHENTICATED, 0, 0);
- log.Print(LL_INTINFO, VNCLOG("Authenticated() donen"));
- return authok;
- }
- void
- vncServer::KillClient(vncClientId clientid)
- {
- vncClientList::iterator i;
- BOOL done = FALSE;
- omni_mutex_lock l(m_clientsLock);
- // Find the client in one of the two lists
- for (i = m_unauthClients.begin(); i != m_unauthClients.end(); i++)
- {
- // Is this the right client?
- if ((*i) == clientid)
- {
- log.Print(LL_INTINFO, VNCLOG("killing unauth clientn"));
- // Ask the client to die
- vncClient *client = GetClient(clientid);
- client->Kill();
- done = TRUE;
- break;
- }
- }
- if (!done)
- {
- for (i = m_authClients.begin(); i != m_authClients.end(); i++)
- {
- // Is this the right client?
- if ((*i) == clientid)
- {
- log.Print(LL_INTINFO, VNCLOG("killing auth clientn"));
- // Yes, so kill it
- vncClient *client = GetClient(clientid);
- client->Kill();
- done = TRUE;
- break;
- }
- }
- }
- log.Print(LL_INTINFO, VNCLOG("KillClient() donen"));
- }
- void
- vncServer::KillAll()
- {
- vncClientList::iterator i;
- omni_mutex_lock l(m_clientsLock);
- // Tell all the authorised clients to die!
- for (i = m_authClients.begin(); i != m_authClients.end(); i++)
- {
- log.Print(LL_INTINFO, VNCLOG("killing auth clientn"));
- // Kill the client
- GetClient(*i)->Kill();
- }
- log.Print(LL_INTINFO, VNCLOG("KillAll() donen"));
- }
- UINT
- vncServer::AuthClientCount()
- {
- omni_mutex_lock l(m_clientsLock);
- return m_authClients.size();
- }
- UINT
- vncServer::UnauthClientCount()
- {
- omni_mutex_lock l(m_clientsLock);
- return m_unauthClients.size();
- }
- void
- vncServer::WaitUntilAuthEmpty()
- {
- omni_mutex_lock l(m_clientsLock);
- // Wait for all the clients to exit
- while (!m_authClients.empty())
- {
- // Wait for a client to quit
- m_clientquitsig->wait();
- }
- }
- // Client info retrieval/setup
- vncClient*
- vncServer::GetClient(vncClientId clientid)
- {
- if ((clientid >= 0) && (clientid < MAX_CLIENTS))
- return m_clientmap[clientid];
- return NULL;
- }
- vncClientList
- vncServer::ClientList()
- {
- vncClientList clients;
- omni_mutex_lock l(m_clientsLock);
- clients = m_authClients;
- return clients;
- }
- void
- vncServer::SetTeleport(vncClientId clientid, BOOL teleport)
- {
- omni_mutex_lock l(m_clientsLock);
- vncClient *client = GetClient(clientid);
- if (client != NULL)
- client->SetTeleport(teleport);
- }
- void
- vncServer::SetCapability(vncClientId clientid, int capability)
- {
- omni_mutex_lock l(m_clientsLock);
- vncClient *client = GetClient(clientid);
- if (client != NULL)
- client->SetCapability(capability);
- }
- void
- vncServer::SetKeyboardEnabled(vncClientId clientid, BOOL enabled)
- {
- omni_mutex_lock l(m_clientsLock);
- vncClient *client = GetClient(clientid);
- if (client != NULL)
- client->EnableKeyboard(enabled);
- }
- void
- vncServer::SetPointerEnabled(vncClientId clientid, BOOL enabled)
- {
- omni_mutex_lock l(m_clientsLock);
- vncClient *client = GetClient(clientid);
- if (client != NULL)
- client->EnablePointer(enabled);
- }
- BOOL
- vncServer::IsTeleport(vncClientId clientid)
- {
- omni_mutex_lock l(m_clientsLock);
- vncClient *client = GetClient(clientid);
- if (client != NULL)
- return client->IsTeleport();
- return FALSE;
- }
- int
- vncServer::GetCapability(vncClientId clientid)
- {
- omni_mutex_lock l(m_clientsLock);
- vncClient *client = GetClient(clientid);
- if (client != NULL)
- return client->GetCapability();
- return 0;
- }
- BOOL
- vncServer::GetKeyboardEnabled(vncClientId clientid)
- {
- omni_mutex_lock l(m_clientsLock);
- vncClient *client = GetClient(clientid);
- if (client != NULL)
- return client->IsKeyboardEnabled();
- return FALSE;
- }
- BOOL
- vncServer::GetPointerEnabled(vncClientId clientid)
- {
- omni_mutex_lock l(m_clientsLock);
- vncClient *client = GetClient(clientid);
- if (client != NULL)
- return client->IsPointerEnabled();
- return FALSE;
- }
- char*
- vncServer::GetClientName(vncClientId clientid)
- {
- omni_mutex_lock l(m_clientsLock);
- vncClient *client = GetClient(clientid);
- if (client != NULL)
- return client->GetClientName();
- return NULL;
- }
- // RemoveClient should ONLY EVER be used by the client to remove itself.
- void
- vncServer::RemoveClient(vncClientId clientid)
- {
- vncClientList::iterator i;
- BOOL done = FALSE;
- omni_mutex_lock l1(m_desktopLock);
- { omni_mutex_lock l2(m_clientsLock);
- // Find the client in one of the two lists
- for (i = m_unauthClients.begin(); i != m_unauthClients.end(); i++)
- {
- // Is this the right client?
- if ((*i) == clientid)
- {
- log.Print(LL_INTINFO, VNCLOG("removing unauthorised clientn"));
- // Yes, so remove the client and kill it
- m_unauthClients.erase(i);
- m_clientmap[clientid] = NULL;
- done = TRUE;
- break;
- }
- }
- if (!done)
- {
- for (i = m_authClients.begin(); i != m_authClients.end(); i++)
- {
- // Is this the right client?
- if ((*i) == clientid)
- {
- log.Print(LL_INTINFO, VNCLOG("removing authorised clientn"));
- // Yes, so remove the client and kill it
- m_authClients.erase(i);
- m_clientmap[clientid] = NULL;
- done = TRUE;
- break;
- }
- }
- }
- // Signal that a client has quit
- m_clientquitsig->signal();
- } // Unlock the clientLock
- // Are there any authorised clients connected?
- if (m_authClients.empty() && (m_desktop != NULL))
- {
- log.Print(LL_STATE, VNCLOG("deleting desktop servern"));
- // Are there locksettings set?
- if (LockSettings() == 1)
- {
- // Yes - lock the machine on disconnect!
- // *** This code actually just starts the screen-saver.
- // So if you want to lock the machine on disconnect, choose
- // a locked screen-saver.
- MessageBeep(MB_OK);
- DefWindowProc(0, WM_SYSCOMMAND, 0xfff0 & SC_SCREENSAVE, 0);
- // *** LockWorkstation only exists in NT 5 and above, so this code doesn't actually
- // work.. For this reason, no mention is made of the locking settings at present in the docs!
- /*
- if (!LockWorkStation())
- log.Print(LL_CONNERR, VNCLOG("client disconnect - failed to lock workstation!n"));
- */
- } else if (LockSettings() > 1)
- {
- char username[UNLEN+1];
- vncService::CurrentUser((char *)&username, sizeof(username));
- if (strcmp(username, "") != 0)
- {
- // Yes - force a user logoff on disconnect!
- if (!ExitWindows(EWX_LOGOFF | EWX_FORCE, 0))
- log.Print(LL_CONNERR, VNCLOG("client disconnect - failed to logoff user!n"));
- }
- }
- // Delete the screen server
- delete m_desktop;
- m_desktop = NULL;
- }
- // Notify anyone interested of the change
- DoNotify(WM_SRV_CLIENT_DISCONNECT, 0, 0);
- log.Print(LL_INTINFO, VNCLOG("RemoveClient() donen"));
- }
- // NOTIFICATION HANDLING!
- // Connect/disconnect notification
- BOOL
- vncServer::AddNotify(HWND hwnd)
- {
- omni_mutex_lock l(m_clientsLock);
- // Add the window handle to the list
- m_notifyList.push_front(hwnd);
- return TRUE;
- }
- BOOL
- vncServer::RemNotify(HWND hwnd)
- {
- omni_mutex_lock l(m_clientsLock);
- // Remove the window handle from the list
- vncNotifyList::iterator i;
- for (i=m_notifyList.begin(); i!=m_notifyList.end(); i++)
- {
- if ((*i) == hwnd)
- {
- // Found the handle, so remove it
- m_notifyList.erase(i);
- return TRUE;
- }
- }
- return FALSE;
- }
- // Send a notification message
- void
- vncServer::DoNotify(UINT message, WPARAM wparam, LPARAM lparam)
- {
- omni_mutex_lock l(m_clientsLock);
- // Send the given message to all the notification windows
- vncNotifyList::iterator i;
- for (i=m_notifyList.begin(); i!=m_notifyList.end(); i++)
- {
- PostMessage((*i), message, wparam, lparam);
- }
- }
- // Client->Desktop update signalling
- void
- vncServer::RequestUpdate()
- {
- omni_mutex_lock l(m_desktopLock);
- if (m_desktop != NULL)
- {
- m_desktop->RequestUpdate();
- }
- }
- // Update handling
- void
- vncServer::TriggerUpdate()
- {
- vncClientList::iterator i;
- omni_mutex_lock l(m_clientsLock);
- // Post this update to all the connected clients
- for (i = m_authClients.begin(); i != m_authClients.end(); i++)
- {
- // Post the update
- GetClient(*i)->TriggerUpdate();
- }
- }
- void
- vncServer::UpdateRect(RECT &rect)
- {
- vncClientList::iterator i;
- omni_mutex_lock l(m_clientsLock);
- // Post this update to all the connected clients
- for (i = m_authClients.begin(); i != m_authClients.end(); i++)
- {
- // Post the update
- GetClient(*i)->UpdateRect(rect);
- }
- }
- void
- vncServer::UpdateRegion(vncRegion ®ion)
- {
- vncClientList::iterator i;
- omni_mutex_lock l(m_clientsLock);
- // Post this update to all the connected clients
- for (i = m_authClients.begin(); i != m_authClients.end(); i++)
- {
- // Post the update
- GetClient(*i)->UpdateRegion(region);
- }
- }
- void
- vncServer::CopyRect(RECT &dest, POINT &source)
- {
- vncClientList::iterator i;
- omni_mutex_lock l(m_clientsLock);
- // Post this update to all the connected clients
- for (i = m_authClients.begin(); i != m_authClients.end(); i++)
- {
- // Post the update
- GetClient(*i)->CopyRect(dest, source);
- }
- }
- void
- vncServer::UpdateMouse()
- {
- vncClientList::iterator i;
- omni_mutex_lock l(m_clientsLock);
- // Post this mouse update to all the connected clients
- for (i = m_authClients.begin(); i != m_authClients.end(); i++)
- {
- // Post the update
- GetClient(*i)->UpdateMouse();
- }
- }
- void
- vncServer::UpdateClipText(LPSTR text)
- {
- vncClientList::iterator i;
- omni_mutex_lock l(m_clientsLock);
- // Post this update to all the connected clients
- for (i = m_authClients.begin(); i != m_authClients.end(); i++)
- {
- // Post the update
- GetClient(*i)->UpdateClipText(text);
- }
- }
- void
- vncServer::UpdatePalette()
- {
- vncClientList::iterator i;
- omni_mutex_lock l(m_clientsLock);
- // Post this update to all the connected clients
- for (i = m_authClients.begin(); i != m_authClients.end(); i++)
- {
- // Post the update
- GetClient(*i)->UpdatePalette();
- }
- }
- void
- vncServer::UpdateLocalClipText(LPSTR text)
- {
- omni_mutex_lock l(m_desktopLock);
- if (m_desktop != NULL)
- m_desktop->SetClipText(text);
- }
- // Name and port number handling
- void
- vncServer::SetName(const char * name)
- {
- // Set the name of the desktop
- if (m_name != NULL)
- {
- free(m_name);
- m_name = NULL;
- }
- m_name = strdup(name);
- }
- void
- vncServer::SetPort(const UINT port)
- {
- if (m_port != port)
- {
- /////////////////////////////////
- // Adjust the listen socket
- // Set the port number to use
- m_port = port;
- // If there is already a listening socket then close and re-open it...
- BOOL socketon = SockConnected();
- SockConnect(FALSE);
- if (socketon)
- SockConnect(TRUE);
- }
- }
- UINT
- vncServer::GetPort()
- {
- return m_port;
- }
- void
- vncServer::SetPassword(const char *passwd)
- {
- memcpy(m_password, passwd, MAXPWLEN);
- }
- void
- vncServer::GetPassword(char *passwd)
- {
- memcpy(passwd, m_password, MAXPWLEN);
- }
- // Remote input handling
- void
- vncServer::EnableInputs(BOOL enable)
- {
- m_enable_inputs = enable;
- }
- BOOL vncServer::InputsEnabled()
- {
- return m_enable_inputs;
- }
- // Socket connection handling
- BOOL
- vncServer::SockConnect(BOOL On)
- {
- // Are we being asked to switch socket connects on or off?
- if (On)
- {
- // Is there a listening socket?
- if (m_socketConn == NULL)
- {
- m_socketConn = new vncSockConnect();
- if (m_socketConn == NULL)
- return FALSE;
- // Are we to use automatic port selection?
- if (m_autoportselect)
- {
- BOOL ok = FALSE;
- // Yes, so cycle through the ports, looking for a free one!
- for (int i=0; i < 99; i++)
- {
- m_port = DISPLAY_TO_PORT(i);
- log.Print(LL_CLIENTS, VNCLOG("trying port number %dn"), m_port);
- // Attempt to connect to the port
- VSocket tempsock;
- if (tempsock.Create())
- {
- if (!tempsock.Connect("localhost", m_port))
- {
- // Couldn't connect, so this port is probably usable!
- if (m_socketConn->Init(this, m_port))
- {
- ok = TRUE;
- break;
- }
- }
- }
- }
- if (!ok)
- {
- delete m_socketConn;
- m_socketConn = NULL;
- return FALSE;
- }
- } else
- {
- // No autoportselect
- if (!m_socketConn->Init(this, m_port))
- {
- delete m_socketConn;
- m_socketConn = NULL;
- return FALSE;
- }
- }
- // Now let's start the HTTP connection stuff
- if (m_httpConn == NULL)
- {
- m_httpConn = new vncHTTPConnect;
- if (m_httpConn != NULL)
- {
- // Start up the HTTP server
- if (!m_httpConn->Init(this,
- PORT_TO_DISPLAY(m_port) + HTTP_PORT_OFFSET))
- {
- delete m_httpConn;
- m_httpConn = NULL;
- return FALSE;
- }
- }
- }
- }
- }
- else
- {
- // *** JNW - Trying to fix up a lock-up when the listening socket closes
- KillAll();
- WaitUntilAuthEmpty();
- // Is there a listening socket?
- if (m_socketConn != NULL)
- {
- // Close the socket
- delete m_socketConn;
- m_socketConn = NULL;
- }
- // Is there an HTTP socket active?
- if (m_httpConn != NULL)
- {
- // Close the socket
- delete m_httpConn;
- m_httpConn = NULL;
- }
- }
- return TRUE;
- }
- BOOL
- vncServer::SockConnected()
- {
- return m_socketConn != NULL;
- }
- // CORBA connection handling
- BOOL
- vncServer::CORBAConnect(BOOL On)
- {
- // Are we being asked to switch CORBA connects on or off?
- if (On)
- {
- // Is there a CORBA object?
- if (m_corbaConn == NULL)
- {
- m_corbaConn = new vncCorbaConnect();
- }
- if (m_corbaConn == NULL)
- return FALSE;
- if (!m_corbaConn->Init(this))
- {
- delete m_corbaConn;
- m_corbaConn = NULL;
- return FALSE;
- }
- }
- else
- {
- // Is there a listening socket?
- if (m_corbaConn != NULL)
- {
- // Close the socket
- delete m_corbaConn;
- m_corbaConn = NULL;
- }
- }
- return TRUE;
- }
- BOOL
- vncServer::CORBAConnected()
- {
- return m_corbaConn != NULL;
- }
- void
- vncServer::GetScreenInfo(int &width, int &height, int &depth)
- {
- rfbServerInitMsg scrinfo;
- omni_mutex_lock l(m_desktopLock);
- log.Print(LL_INTINFO, VNCLOG("GetScreenInfo calledn"));
- // Is a desktop object currently active?
- if (m_desktop == NULL)
- {
- vncDesktop desktop;
- // No, so create a dummy desktop and interrogate it
- if (!desktop.Init(this))
- {
- scrinfo.framebufferWidth = 0;
- scrinfo.framebufferHeight = 0;
- scrinfo.format.bitsPerPixel = 0;
- }
- else
- {
- desktop.FillDisplayInfo(&scrinfo);
- }
- }
- else
- {
- m_desktop->FillDisplayInfo(&scrinfo);
- }
- // Get the info from the scrinfo structure
- width = scrinfo.framebufferWidth;
- height = scrinfo.framebufferHeight;
- depth = scrinfo.format.bitsPerPixel;
- }