I need to control a running VNC server via socket with telnet on localhost. This is meant to provide an easy to automate interface for other processes starting and then manipulating a VNC server locally.
Because I definitely need to have such an interface, I won't just ask for anybody to implement it but rather provide a patch here (see below) that does exactly this.
Question to the developers: Would you like to integrate this patch into UltraVNC code? Do you need additional modifications prior to integration?
Manipulation options are
- listing of active clients
- switching on/of keybord and/or mouse and/or file transfer permissions for each client separately
- switching on/off keybord and/or mouse locally (only if there are active clients ...)
- setting of password,
- adding clients via repeater
- killing clients
- shutting down server
- and more
The existence and the port number of the telnet control port is configurable in ultravnc.ini. The telnet control port in release build is only bound to loopback device.
Here a short how to try (you need gnu patch):
- Take snapshot of today (revision 860)
- cd "...\ultravnc\UltraVNC Project Root\UltraVNC"
- patch -p 1 < ultravnc-with-telnet-ctrl.diff
- build winvnc with vs 10 (tested, with vc 9, 11 or 12 you will still have to add vncTelnetCtrl.* to project winvnc)
- add the following two lines to ultravnc.ini, section [admin]:
TelnetCtrlPort=12345
EnableDriver=1
- run winvnc.exe
- open a cmd.exe, type telnet localhost 12345
- type help and see a usage message explaining what exactly you can do
- play with it ...
Thanks for trying!
Comments?
Cheers
Hans
Code: Select all
diff -Naur UltraVNC-orig/winvnc/winvnc/vncclient.cpp UltraVNC/winvnc/winvnc/vncclient.cpp
--- UltraVNC-orig/winvnc/winvnc/vncclient.cpp 2013-11-02 00:00:46.000000000 +0100
+++ UltraVNC/winvnc/winvnc/vncclient.cpp 2014-03-25 09:02:47.439091300 +0100
@@ -3125,7 +3125,12 @@
fUserOk = m_client->DoFTUserImpersonation();
}
- if (!m_client->m_keyboardenabled || !m_client->m_pointerenabled) fUserOk = false; //PGM
+ switch(m_client->m_ftEnableMode)
+ {
+ case vncClient::FT_DISABLED: fUserOk = false; break;
+ case vncClient::FT_AUTOMATIC: if (!m_client->m_keyboardenabled || !m_client->m_pointerenabled) fUserOk = false; /*PGM*/ break;
+ case vncClient::FT_ENABLED: fUserOk = true; break;
+ }
omni_mutex_lock l(m_client->GetUpdateLock(),88);
@@ -3587,7 +3592,7 @@
else
ft.contentType = rfbFileTransferAccess; // Viewer with old FT protocole
- if (!bOldFTProtocole && m_server->FileTransferEnabled() && m_client->m_server->RemoteInputsEnabled() && fUserOk)
+ if (!bOldFTProtocole && m_server->FileTransferEnabled() && fUserOk)
ft.size = Swap32IfLE(1);
else
ft.size = Swap32IfLE(-1);
@@ -4141,6 +4146,8 @@
m_socket = NULL;
m_client_name = 0;
+ m_client_port = 0;
+ m_ftEnableMode = FT_AUTOMATIC;
// Initialise mouse fields
m_mousemoved = FALSE;
@@ -4367,6 +4374,8 @@
else
m_client_name = _strdup("<unknown>");
+ m_client_port = m_socket->GetPeerPort();
+
// Save the client id
m_id = newid;
@@ -4624,6 +4633,13 @@
return m_client_name;
}
+// Functions used to set and retrieve the client settings
+int
+vncClient::GetClientPort()
+{
+ return m_client_port;
+}
+
// Enabling and disabling clipboard/GFX updates
void
vncClient::DisableProtocol()
@@ -6215,3 +6231,4 @@
m_socket->SendExact((char *)&msg, sz_rfbNotifyPluginStreamingMsg, rfbNotifyPluginStreaming);
m_socket->SetPluginStreamingOut();
}
+
diff -Naur UltraVNC-orig/winvnc/winvnc/vncclient.h UltraVNC/winvnc/winvnc/vncclient.h
--- UltraVNC-orig/winvnc/winvnc/vncclient.h 2013-03-27 21:22:24.000000000 +0100
+++ UltraVNC/winvnc/winvnc/vncclient.h 2014-03-25 09:02:47.454716200 +0100
@@ -90,6 +90,8 @@
class vncClient
{
public:
+ enum FtEnableMode {FT_DISABLED, FT_AUTOMATIC, FT_ENABLED};
+
// Constructor/destructor
vncClient();
virtual ~vncClient();
@@ -156,12 +158,17 @@
// Functions for setting & getting the client settings
virtual void EnableKeyboard(BOOL enable) {m_keyboardenabled = enable;};
+ virtual BOOL IsKeyboardEnabled(){return m_keyboardenabled;};
virtual void EnablePointer(BOOL enable) {m_pointerenabled = enable;};
+ virtual BOOL IsPointerEnabled(){return m_pointerenabled;};
+ virtual void SetFileTransferMode(FtEnableMode ftEnableMode) {m_ftEnableMode = ftEnableMode;}
+ virtual FtEnableMode GetFileTransferEnableMode(){return m_ftEnableMode;}
virtual void EnableJap(bool enable) {m_jap = enable;};
virtual void SetCapability(int capability) {m_capability = capability;};
virtual int GetCapability() {return m_capability;};
virtual const char *GetClientName();
+ virtual int GetClientPort();
virtual vncClientId GetClientId() {return m_id;};
// Disable/enable protocol messages to the client
@@ -396,6 +403,7 @@
BOOL m_IsLoopback;
BOOL m_keyboardenabled;
BOOL m_pointerenabled;
+ FtEnableMode m_ftEnableMode;
bool m_jap;
int m_capability;
vncClientId m_id;
@@ -410,6 +418,7 @@
// The socket
VSocket *m_socket;
char *m_client_name;
+ int m_client_port;
// The client thread
omni_thread *m_thread;
diff -Naur UltraVNC-orig/winvnc/winvnc/vncproperties.cpp UltraVNC/winvnc/winvnc/vncproperties.cpp
--- UltraVNC-orig/winvnc/winvnc/vncproperties.cpp 2013-11-08 19:55:46.000000000 +0100
+++ UltraVNC/winvnc/winvnc/vncproperties.cpp 2014-03-25 09:02:47.454716200 +0100
@@ -2263,6 +2263,10 @@
m_server->SetAuthHosts(0);
}
+ bool enableTelnetCtrl = myIniFile.ReadInt("admin", "EnableTelnetCtrl", false)?true:false;
+ int port = myIniFile.ReadInt("admin", "TelnetCtrlPort", 59000);
+ m_server->EnableTelnetCtrl(enableTelnetCtrl, port);
+
vnclog.Print(LL_INTINFO, VNCLOG("***** DBG - Load User Preferences\n"));
// Set the default user prefs
diff -Naur UltraVNC-orig/winvnc/winvnc/vncserver.cpp UltraVNC/winvnc/winvnc/vncserver.cpp
--- UltraVNC-orig/winvnc/winvnc/vncserver.cpp 2013-11-04 18:14:34.000000000 +0100
+++ UltraVNC/winvnc/winvnc/vncserver.cpp 2014-03-25 09:02:47.470341100 +0100
@@ -46,6 +46,8 @@
#include "vncmenu.h"
+#include "vncTelnetCtrl.h"
+
#include "Localization.h" // ACT : Add localization on messages
bool g_Server_running;
extern bool g_Desktop_running;
@@ -241,12 +243,20 @@
//adzm 2010-05-12 - dsmplugin config
m_szDSMPluginConfig[0] = '\0';
OS_Shutdown=false;
+
+ m_telnetCtrl = NULL;
}
vncServer::~vncServer()
{
vnclog.Print(LL_STATE, VNCLOG("shutting down server object1\n"));
+ if(m_telnetCtrl != NULL)
+ {
+ delete m_telnetCtrl;
+ m_telnetCtrl = NULL;
+ }
+
// We don't want to retry when we are shutting down...
m_fAutoReconnect = FALSE;
m_fIdReconnect = FALSE;
@@ -341,6 +351,33 @@
g_Server_running=false;
}
+
+void
+vncServer::EnableTelnetCtrl(bool enable, int port)
+{
+ if(enable)
+ {
+ if(m_telnetCtrl && m_telnetCtrl->GetPort() == port)
+ {
+ // nothing to do
+ }
+ else
+ {
+ if(m_telnetCtrl)
+ {
+ delete m_telnetCtrl; //runs on wrong port, need new
+ }
+ m_telnetCtrl = new vncTelnetCtrl(this, &fShutdownOrdered, GetCurrentThreadId(), port);
+ }
+ }
+ else
+ {
+ delete m_telnetCtrl;
+ m_telnetCtrl = NULL;
+ }
+}
+
+
void
vncServer::ShutdownServer()
{
diff -Naur UltraVNC-orig/winvnc/winvnc/vncserver.h UltraVNC/winvnc/winvnc/vncserver.h
--- UltraVNC-orig/winvnc/winvnc/vncserver.h 2013-11-04 18:14:34.000000000 +0100
+++ UltraVNC/winvnc/winvnc/vncserver.h 2014-03-25 09:02:47.470341100 +0100
@@ -38,6 +38,7 @@
// and via the ORB interface
extern bool fShutdownOrdered;
class vncServer;
+class vncTelnetCtrl;
#if (!defined(_WINVNC_VNCSERVER))
#define _WINVNC_VNCSERVER
@@ -163,6 +164,8 @@
UINT m_port;
UINT m_port_http; // TightVNC 1.2.7
+ virtual void EnableTelnetCtrl(bool enable, int port);
+
virtual void ShutdownServer();
protected:
@@ -604,6 +607,8 @@
// adzm 2010-08
int m_socketKeepAliveTimeout;
bool clearconsole;
+
+ vncTelnetCtrl* m_telnetCtrl;
};
#endif
diff -Naur UltraVNC-orig/winvnc/winvnc/vncTelnetCtrl.cpp UltraVNC/winvnc/winvnc/vncTelnetCtrl.cpp
--- UltraVNC-orig/winvnc/winvnc/vncTelnetCtrl.cpp 1970-01-01 01:00:00.000000000 +0100
+++ UltraVNC/winvnc/winvnc/vncTelnetCtrl.cpp 2014-03-25 09:02:47.470341100 +0100
@@ -0,0 +1,660 @@
+#include "vncTelnetCtrl.h"
+#include "vncserver.h"
+
+
+
+vncTelnetCtrl::vncTelnetCtrl(vncServer* pServer, bool* pOrderShutdown, DWORD threadId, int port)
+ :m_pServer(pServer),
+ m_threadHandle(0),
+ m_sock(0),
+ m_threadId(threadId),
+ m_pOrderShutdown(pOrderShutdown),
+ m_port(port)
+{
+ bool wsaInitailized = false;
+ try
+ {
+ WORD wVersionRequested = MAKEWORD(2, 0);
+ WSADATA wsaData;
+ if (WSAStartup(wVersionRequested, &wsaData))throw -1;
+ wsaInitailized = true;
+
+ if ((m_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)throw -1;
+ struct sockaddr_in addr;
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(m_port);
+#ifdef _DEBUG
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+#else
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+#endif
+ if (bind(m_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) throw -1;
+ if (listen(m_sock, 5) < 0) throw -1;
+
+ DWORD dwTId;
+ m_threadHandle = CreateThread(NULL, 0, &threadProc, this, 0, &dwTId);
+ if(!m_threadHandle)throw -1;
+ }
+ catch(...)
+ {
+ if(m_sock)
+ {
+ shutdown(m_sock, SD_BOTH);
+ closesocket(m_sock);
+ }
+ if(m_threadHandle)
+ {
+ WaitForSingleObject( m_threadHandle, INFINITE );
+ CloseHandle(m_threadHandle);
+ }
+ if(wsaInitailized)
+ {
+ WSACleanup();
+ }
+ }
+}
+
+vncTelnetCtrl::~vncTelnetCtrl(void)
+{
+ shutdown(m_sock, SD_BOTH);
+ closesocket(m_sock);
+ WaitForSingleObject( m_threadHandle, INFINITE );
+ CloseHandle(m_threadHandle);
+ WSACleanup();
+}
+
+DWORD WINAPI vncTelnetCtrl::threadProc(LPVOID pThis)
+{
+ return static_cast<vncTelnetCtrl*>(pThis)->Listen();
+}
+
+DWORD vncTelnetCtrl::Listen()
+{
+ SOCKET accSock = 0;
+ while ((accSock = accept(m_sock, NULL, 0)) != SOCKET_ERROR)
+ {
+ DWORD dwTId;
+ accInfo* pai = new accInfo;
+ pai->m_Sock=accSock;
+ pai->m_ThrHandle = CreateThread(NULL, 0, &accProc, pai, 0, &dwTId);
+ pai->m_pThis = this;
+ pai->m_ShutdownOnDie = false;
+ if(pai->m_ThrHandle)
+ {
+ m_accList.push_back(pai);
+ }
+ else
+ {
+ shutdown(pai->m_Sock, SD_BOTH);
+ closesocket(pai->m_Sock);
+ delete pai;
+ }
+ joinThreads(false);
+ }
+ joinThreads(true);
+ return 0;
+}
+
+void vncTelnetCtrl::joinThreads(bool terminateThreads)
+{
+ bool removedOne=false;
+ do
+ {
+ removedOne=false;
+ for(std::list<accInfo*>::iterator i = m_accList.begin(); i != m_accList.end(); i++)
+ {
+ if((terminateThreads) && ((*i)->m_Sock != 0))
+ {
+ shutdown((*i)->m_Sock, SD_BOTH);
+ closesocket((*i)->m_Sock);
+ (*i)->m_Sock = 0;
+ }
+ if((*i)->m_Sock == 0)
+ {
+ WaitForSingleObject((*i)->m_ThrHandle, INFINITE);
+ CloseHandle((*i)->m_ThrHandle);
+ delete *i;
+ m_accList.remove(*i);
+ removedOne = true;
+ break;
+ }
+ }
+ }
+ while(removedOne);
+}
+
+DWORD WINAPI vncTelnetCtrl::accProc(LPVOID pAccInfo)
+{
+ accInfo* pai = static_cast<accInfo*>(pAccInfo);
+ int bytes = 0;
+ char buf[1];
+ char cmd[1024];
+ char* pCmd = cmd;
+ send(pai->m_Sock, "> ", 2, 0);
+ while((bytes=recv(pai->m_Sock, buf, sizeof(buf), 0))>0)
+ {
+ // echo
+ //send(pai->m_Sock, buf, 1, 0);
+
+ if(*buf == '\r')
+ {
+ //ignore otherwise
+ }
+ else
+ if(*buf == '\n')
+ {
+ *pCmd=0;
+ pCmd=cmd;
+ const char* pRes = NULL;
+ int ResLen = 0;
+ bool exitNow = !pai->m_pThis->DoCommand(cmd, pRes, ResLen, pai);
+ send(pai->m_Sock, pRes, ResLen, 0);
+ delete[] pRes;
+ if(exitNow)
+ {
+ shutdown(pai->m_Sock, SD_BOTH);
+ closesocket(pai->m_Sock);
+ }
+ else
+ {
+ send(pai->m_Sock, "> ", 2, 0);
+ }
+ }
+ else
+ {
+ if(pCmd<(cmd+sizeof(cmd)-1))
+ {
+ *pCmd++=*buf;
+ }
+ else
+ {
+ send(pai->m_Sock, "bye: command too long\r\n", 23, 0);
+ shutdown(pai->m_Sock, SD_BOTH);
+ closesocket(pai->m_Sock);
+ }
+ }
+ }
+ closesocket(pai->m_Sock);
+ pai->m_Sock = 0;
+ if(pai->m_ShutdownOnDie)
+ {
+ *(pai->m_pThis->m_pOrderShutdown) = true;
+ }
+ return 0;
+}
+
+
+bool vncTelnetCtrl::DoCommand(const char* pCmdRaw, const char*& pRes, int& ResLen, accInfo* pAi)
+{
+ bool more = true;
+ bool understood = false;
+
+ // evaluate backspace
+ char cmd[1024];
+ char* pCmd = cmd;
+ while(*pCmdRaw)
+ {
+ if(*pCmdRaw != 0x08)
+ {
+ *pCmd = *pCmdRaw;
+ pCmd++;
+ }
+ else
+ {
+ if(pCmd > cmd)
+ {
+ pCmd--;
+ }
+ }
+ pCmdRaw++;
+ }
+ *pCmd = 0;
+ pCmd = cmd;
+ // --
+
+ if(strcmp(pCmd, "help") == 0)
+ {
+ pRes = allocateResponse(
+ "\r\n"
+ "Usage:\r\n"
+ "\r\n"
+ "Commands:\r\n"
+ "\r\n"
+ " help Shows this help text.\r\n"
+ "\r\n"
+ " list Returns a list of clients that are logged in.\r\n"
+ " Values listed:\r\n"
+ " <clientid> ID of client (to be used with other commands)\r\n"
+ " <PeerAddress>:<PeerPort> identifying the connected client\r\n"
+ " k:<on|off> keyboard input state\r\n"
+ " m:<on|off> mouse input state\r\n"
+ " f:<enabled|automaticdisabled>\r\n"
+ " file transfer enable state, values:\r\n"
+ " enabled file transfer enabled\r\n"
+ " automatic file transfer enabled if all input on\r\n"
+ " disabled file transfer disabled\r\n"
+ "\r\n"
+ " passwd <password> Sets a new password.\r\n"
+ "\r\n"
+ " addclient <address>:<port> <id>\r\n"
+ " Opens a client connection to the repeater at the given address\r\n"
+ " and listening at the given port under the given id.\r\n"
+ " The ID gets automatically prefixed by 'ID:'.\r\n"
+ " Any ID the repeater can handle is applicable.\r\n"
+ "\r\n"
+ " input <on|off> <<clientid>|local>\r\n"
+ " Switches keyboard and mouse input on or off for the given\r\n"
+ " client ID or for the local desktop. See also 'list'.\r\n"
+ "\r\n"
+ " mouse <on|off> <<clientid>|local>\r\n"
+ " Switches mouse input on or off for the given\r\n"
+ " client ID or for the local desktop. See also 'list'.\r\n"
+ "\r\n"
+ " keyboard <on|off> <<clientid>|local>\r\n"
+ " Switches keyboard on or off for the given\r\n"
+ " client ID or for the local desktop. See also 'list'.\r\n"
+ "\r\n"
+ " files <enable|automatic|disable> <clientid>\r\n"
+ " Switches file transfer enable state as given.\r\n"
+ " For explanation of the modes see 'list'.\r\n"
+ "\r\n"
+ " kill <clientid>\r\n"
+ " Kills the given client ID. See also 'list'.\r\n"
+ "\r\n"
+ " quit Exits from telnet interface.\r\n"
+ "\r\n"
+ " exit Exits from telnet interface.\r\n"
+ "\r\n"
+ " shutdown\r\n"
+ " Immediately shuts down the vnc server.\r\n"
+ "\r\n"
+ " shutdownondie\r\n"
+ " Sets a mode that shuts down the vnc server immediately\r\n"
+ " if telnet connection has an unexpected connection loss.\r\n"
+ " Useful if telnet port is used for control by another tool.\r\n"
+ " Quitting normally by exit or quit doesn't issue a shutdown \r\n"
+ " but instead resets the shutdownondie mode\r\n"
+ "ok\r\n",
+ ResLen);
+ understood = true;
+ }
+ else
+ if(strcmp(pCmd, "quit") == 0)
+ {
+ pAi->m_ShutdownOnDie = false;
+ pRes = allocateResponse("bye\r\n", ResLen);
+ more = false;
+ understood = true;
+ }
+ else
+ if(strcmp(pCmd, "exit") == 0)
+ {
+ pAi->m_ShutdownOnDie = false;
+ pRes = allocateResponse("bye\r\n", ResLen);
+ more = false;
+ understood = true;
+ }
+ else
+ if(strcmp(pCmd, "list") == 0)
+ {
+ std::string res;
+ {
+ omni_mutex_lock lock(m_pServer->m_clientsLock,10001);
+ vncClientList l = m_pServer->ClientList();
+ for(std::list<vncClientId>::iterator i = l.begin(); i != l.end(); i++)
+ {
+ vncClientId ClientId = *i;
+ vncClient* pClient = m_pServer->GetClient(ClientId);
+ const char* pPeerName = pClient->GetClientName();
+ int peerPort = pClient->GetClientPort();
+ bool keyboardEnabled = pClient->IsKeyboardEnabled()?true:false;
+ bool pointerEnabled = pClient->IsPointerEnabled()?true:false;
+ vncClient::FtEnableMode ftMode = pClient->GetFileTransferEnableMode();
+ const char* pFtMode = "";
+ switch(ftMode)
+ {
+ case vncClient::FT_DISABLED: pFtMode="f:disabled"; break;
+ case vncClient::FT_AUTOMATIC: pFtMode="f:automatic"; break;
+ case vncClient::FT_ENABLED: pFtMode="f:enabled"; break;
+ }
+ char line[1024];
+ sprintf(line,"%d %s:%d %s %s %s\r\n", static_cast<int>(ClientId), pPeerName, peerPort, (keyboardEnabled?"k:on":"k:off"), (pointerEnabled?"m:on":"m:off"), pFtMode);
+ res.append(line);
+ }
+ }
+ pRes = allocateResponse(res.c_str(), ResLen);
+ understood = true;
+ }
+ else
+ if(strncmp(pCmd, "passwd ", 7) == 0)
+ {
+ pCmd+=7;
+ char encpasswd[MAXPWLEN+1];
+ encpasswd[MAXPWLEN]=0;
+ vncEncryptPasswd(pCmd, encpasswd);
+ m_pServer->SetPassword(encpasswd);
+ pRes = allocateResponse("ok\r\n", ResLen);
+ understood = true;
+ }
+ else
+ if(strncmp(pCmd, "addclient ", 9) == 0)
+ {
+ pCmd+=9;
+
+ // eat extra white space
+ while((*pCmd == ' ') || (*pCmd == '\t'))
+ {
+ pCmd++;
+ }
+
+ char* pAddress = new char[strlen(pCmd)+1];
+ char* pAddressChar=pAddress;
+ while((*pCmd != ':') && (*pCmd != 0))
+ {
+ *pAddressChar = *pCmd;
+ pAddressChar++;
+ pCmd++;
+ }
+ *pAddressChar = 0;
+
+ bool good = true;
+ if(*pCmd != ':')
+ {
+ good = false;
+ }
+
+ int port = 0;
+ if(good)
+ {
+ pCmd++;
+ char* pEnd = NULL;
+ port = strtoul(pCmd, &pEnd, 10);
+ if(port <= 0xffff)
+ {
+ if((*pEnd == ' ') || (*pEnd == '\t'))
+ {
+ pCmd = pEnd+1;
+ }
+ else
+ {
+ good = false;
+ }
+ }
+ else
+ {
+ good = false;
+ }
+ }
+
+ if(good)
+ {
+ // eat extra white space
+ while((*pCmd == ' ') || (*pCmd == '\t'))
+ {
+ pCmd++;
+ }
+ }
+
+ //unsigned id = 0;
+ //if(good)
+ //{
+ // char* pEnd = NULL;
+ // id = strtoul(pCmd, &pEnd, 10);
+ // if(pCmd == pEnd)
+ // {
+ // good = false;
+ // }
+ // pCmd = pEnd;
+ //}
+ char* pId = NULL;
+ if(good)
+ {
+ pId = new char[strlen(pCmd)+1];
+ char* pIdChar=pId;
+ while((*pCmd != ' ') && (*pCmd != '\t') && (*pCmd != 0))
+ {
+ *pIdChar = *pCmd;
+ pIdChar++;
+ pCmd++;
+ }
+ *pIdChar = 0;
+ if(pIdChar == pId)
+ {
+ good = false;
+ }
+ }
+
+ if(good)
+ {
+ // eat extra white space
+ while((*pCmd == ' ') || (*pCmd == '\t'))
+ {
+ pCmd++;
+ }
+ }
+
+ if(good)
+ {
+ if(*pCmd != 0)
+ {
+ good = false;
+ }
+ }
+
+ if(good)
+ {
+ VSocket *tmpsock = new VSocket;
+ tmpsock->Create();
+ if (tmpsock->Connect(pAddress, port))
+ {
+ char finalidcode[_MAX_PATH];
+ ZeroMemory(finalidcode, sizeof(finalidcode));
+ strcpy(finalidcode, "ID:");
+ //sprintf(finalidcode+3, "%d", id);
+ strcpy(finalidcode+3, pId);
+ tmpsock->Send(finalidcode,50);
+ tmpsock->SetTimeout(0);
+ m_pServer->AddClient(tmpsock, FALSE, TRUE, 0, NULL, finalidcode, pAddress, port);
+ pRes = allocateResponse("ok\r\n", ResLen);
+ }
+ else
+ {
+ pRes = allocateResponse("nok: Failed to connect.\r\n", ResLen);
+ delete tmpsock;
+ }
+ understood = true;
+ }
+
+ delete pAddress;
+ delete pId;
+ }
+ else
+ if((strncmp(pCmd, "input ", 6) == 0) || (strncmp(pCmd, "mouse ", 6) == 0) || (strncmp(pCmd, "keyboard ", 9) == 0))
+ {
+ bool mouse = false;
+ bool kbd = false;
+ switch(*pCmd)
+ {
+ case 'm': pCmd+=6; mouse = true; break;
+ case 'k': pCmd+=9; kbd = true; break;
+ case 'i': pCmd+=6; mouse = true; kbd = true; break;
+ }
+ bool onoffok=false;
+ bool on=false;
+ if(strncmp(pCmd, "on ", 3) == 0)
+ {
+ onoffok=true;
+ on=true;
+ pCmd+=3;
+ }
+ else if(strncmp(pCmd, "off ", 4) == 0)
+ {
+ onoffok=true;
+ on=false;
+ pCmd+=4;
+ }
+
+ int id = 0;
+ int idok = false;
+ if(onoffok)
+ {
+ char* pBehind = NULL;
+ id = strtol(pCmd, &pBehind, 10);
+ if((pBehind != pCmd) && (*pBehind == 0))
+ {
+ idok=true;
+ }
+ }
+
+ if(idok)
+ {
+ vncClientId ClientId = id;
+ {
+ omni_mutex_lock lock(m_pServer->m_clientsLock,10002);
+ vncClient* pClient = m_pServer->GetClient(ClientId);
+ if(pClient)
+ {
+ if(kbd)pClient->EnableKeyboard(on);
+ if(mouse)pClient->EnablePointer(on);
+ pRes = allocateResponse("ok\r\n", ResLen);
+ }
+ else
+ {
+ pRes = allocateResponse("nok: Client not found.\r\n", ResLen);
+ }
+ }
+ understood = true;
+ }
+ else
+ if(strcmp(pCmd, "local") == 0)
+ {
+ if(kbd==mouse)
+ {
+ if(on || (m_pServer->AuthClientCount() > 0))
+ {
+ m_pServer->DisableLocalInputs(!on);
+ pRes = allocateResponse("ok\r\n", ResLen);
+ }
+ else
+ {
+ pRes = allocateResponse("nok: Ignoring 'input off local' as no authenticated clients are connected.\r\n", ResLen);
+ }
+ }
+ else
+ {
+ pRes = allocateResponse("nok: Cannot enable/disable local mouse and keyboard input seperately.\r\n", ResLen);
+ }
+ understood = true;
+ }
+ }
+ else
+ if((strncmp(pCmd, "files ", 6) == 0))
+ {
+ pCmd+=6;
+ vncClient::FtEnableMode mode = vncClient::FT_AUTOMATIC;
+ bool modeok=false;
+ if(strncmp(pCmd, "disable ", 8) == 0)
+ {
+ mode=vncClient::FT_DISABLED;
+ modeok=true;
+ pCmd+=8;
+ }
+ else
+ if(strncmp(pCmd, "automatic ", 10) == 0)
+ {
+ mode=vncClient::FT_AUTOMATIC;
+ modeok=true;
+ pCmd+=10;
+ }
+ else
+ if(strncmp(pCmd, "enable ", 7) == 0)
+ {
+ mode=vncClient::FT_ENABLED;
+ modeok=true;
+ pCmd+=7;
+ }
+
+ int id = 0;
+ int idok = false;
+ if(modeok)
+ {
+ char* pBehind = NULL;
+ id = strtol(pCmd, &pBehind, 10);
+ if((pBehind != pCmd) && (*pBehind == 0))
+ {
+ idok=true;
+ }
+ }
+
+ if(idok)
+ {
+ vncClientId ClientId = id;
+ {
+ omni_mutex_lock lock(m_pServer->m_clientsLock,10002);
+ vncClient* pClient = m_pServer->GetClient(ClientId);
+ if(pClient)
+ {
+ pClient->SetFileTransferMode(mode);
+ pRes = allocateResponse("ok\r\n", ResLen);
+ }
+ else
+ {
+ pRes = allocateResponse("nok: Client not found.\r\n", ResLen);
+ }
+ }
+ understood = true;
+ }
+ }
+ else
+ if(strncmp(pCmd, "kill ", 5) == 0)
+ {
+ pCmd+=5;
+ int id = 0;
+ int idok = false;
+ id = atoi(pCmd);
+ if(id)
+ {
+ idok=true;
+ }
+
+ if(idok)
+ {
+ vncClientId ClientId = id;
+ m_pServer->KillClient(ClientId);
+ pRes = allocateResponse("ok\r\n", ResLen);
+ understood = true;
+ }
+ }
+ else
+ if(strcmp(pCmd, "shutdown") == 0)
+ {
+ pAi->m_ShutdownOnDie = false;
+ *m_pOrderShutdown = true;
+ PostThreadMessage(m_threadId, WM_QUIT, 0,0);
+ pRes = allocateResponse("bye\r\n", ResLen);
+ more = false;
+ understood = true;
+ }
+ else
+ if(strcmp(pCmd, "shutdownondie") == 0)
+ {
+ pRes = allocateResponse("ok\r\n", ResLen);
+ pAi->m_ShutdownOnDie = true;
+ understood = true;
+ }
+
+ if(!understood)
+ {
+ pRes = allocateResponse("nok: Unknown command or bad arguments. Type help for usage.\r\n", ResLen);
+ }
+
+ return more;
+}
+
+const char* vncTelnetCtrl::allocateResponse(const char* pRes, int& ResLen)
+{
+ ResLen = strlen(pRes);
+ char* pBuf = new char[ResLen+1];
+ strcpy(pBuf, pRes);
+ return pBuf;
+}
\ Kein Zeilenumbruch am Dateiende.
diff -Naur UltraVNC-orig/winvnc/winvnc/vncTelnetCtrl.h UltraVNC/winvnc/winvnc/vncTelnetCtrl.h
--- UltraVNC-orig/winvnc/winvnc/vncTelnetCtrl.h 1970-01-01 01:00:00.000000000 +0100
+++ UltraVNC/winvnc/winvnc/vncTelnetCtrl.h 2014-03-25 09:02:47.485966000 +0100
@@ -0,0 +1,33 @@
+#pragma once
+#include "stdhdrs.h"
+#include <list>
+class vncServer;
+class vncTelnetCtrl
+{
+public:
+ vncTelnetCtrl(vncServer* pServer, bool* pOrderShutdown, DWORD ThreadId, int port);
+ virtual ~vncTelnetCtrl();
+ int GetPort() { return m_port; }
+private:
+ struct accInfo
+ {
+ SOCKET m_Sock;
+ HANDLE m_ThrHandle;
+ vncTelnetCtrl* m_pThis;
+ bool m_ShutdownOnDie;
+ };
+ static DWORD WINAPI threadProc(LPVOID pThis);
+ static DWORD WINAPI accProc(LPVOID pAccInfo);
+ static const char* allocateResponse(const char* pRes, int& ResLen);
+ DWORD Listen();
+ void joinThreads(bool terminateThreads);
+ bool DoCommand(const char* pCmdRaw, const char*& pRes, int& ResLen, accInfo* pAi);
+ vncServer* m_pServer;
+ HANDLE m_threadHandle;
+ SOCKET m_sock;
+ std::list<accInfo*> m_accList;
+ DWORD m_threadId;
+ bool* m_pOrderShutdown;
+ int m_port;
+};
+
diff -Naur UltraVNC-orig/winvnc/winvnc/vsocket.cpp UltraVNC/winvnc/winvnc/vsocket.cpp
--- UltraVNC-orig/winvnc/winvnc/vsocket.cpp 2013-03-27 21:22:24.000000000 +0100
+++ UltraVNC/winvnc/winvnc/vsocket.cpp 2014-03-25 09:02:47.485966000 +0100
@@ -405,6 +405,21 @@
}
////////////////////////////
+////////////////////////////
+
+VCard
+VSocket::GetPeerPort()
+{
+ struct sockaddr_in sockinfo;
+ int sockinfosize = sizeof(sockinfo);
+
+ // Get the peer address for the client socket
+ getpeername(sock, (struct sockaddr *)&sockinfo, &sockinfosize);
+
+ return ntohs(sockinfo.sin_port);
+}
+
+////////////////////////////
VString
VSocket::GetSockName()
diff -Naur UltraVNC-orig/winvnc/winvnc/vsocket.h UltraVNC/winvnc/winvnc/vsocket.h
--- UltraVNC-orig/winvnc/winvnc/vsocket.h 2012-11-07 09:19:46.000000000 +0100
+++ UltraVNC/winvnc/winvnc/vsocket.h 2014-03-25 09:02:47.485966000 +0100
@@ -116,6 +116,12 @@
// This string MUST be copied before the next socket call...
VString GetPeerName();
+ // GetPeerPort
+ // If the socket is connected then this returns the name
+ // of the machine to which it is connected.
+ // This string MUST be copied before the next socket call...
+ VCard GetPeerPort();
+
// GetSockName
// If the socket exists then the name of the local machine
// is returned. This string MUST be copied before the next
diff -Naur UltraVNC-orig/winvnc/winvnc/winvnc.cpp UltraVNC/winvnc/winvnc/winvnc.cpp
--- UltraVNC-orig/winvnc/winvnc/winvnc.cpp 2013-11-04 18:14:34.000000000 +0100
+++ UltraVNC/winvnc/winvnc/winvnc.cpp 2014-03-25 09:02:47.485966000 +0100
@@ -40,6 +40,7 @@
#include "winvnc.h"
#include "vncserver.h"
+#include "vncTelnetCtrl.h"
#include "vncmenu.h"
#include "vncinsthandler.h"
#include "vncservice.h"
@@ -1027,6 +1028,7 @@
//vnclog.Print(LL_INTINFO, VNCLOG("***** DBG - Previous instance checked - Trying to create server\n"));
// CREATE SERVER
vncServer server;
+ DWORD dwTId;
// Set the name and port number
server.SetName(szAppName);
@@ -1051,7 +1053,6 @@
//vnclog.Print(LL_STATE, VNCLOG("################## Creating Imp Thread : %d \n"), nn);
HANDLE threadHandle;
- DWORD dwTId;
threadHandle = CreateThread(NULL, 0, imp_desktop_thread, &server, 0, &dwTId);
if (threadHandle)
diff -Naur UltraVNC-orig/winvnc/winvnc/winvnc.vcxproj UltraVNC/winvnc/winvnc/winvnc.vcxproj
--- UltraVNC-orig/winvnc/winvnc/winvnc.vcxproj 2013-12-05 21:11:22.000000000 +0100
+++ UltraVNC/winvnc/winvnc/winvnc.vcxproj 2014-03-25 09:02:47.501590900 +0100
@@ -1221,6 +1221,7 @@
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
+ <ClCompile Include="vncTelnetCtrl.cpp" />
<ClCompile Include="vnctimedmsgbox.cpp">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -1325,6 +1326,7 @@
<ClInclude Include="vncservice.h" />
<ClInclude Include="vncsetauth.h" />
<ClInclude Include="vncsockconnect.h" />
+ <ClInclude Include="vncTelnetCtrl.h" />
<ClInclude Include="vnctimedmsgbox.h" />
<ClInclude Include="vsocket.h" />
<ClInclude Include="vtypes.h" />