plugins/consoles/rcons/server/win32/Server.cpp
changeset 0 7f656887cf89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/consoles/rcons/server/win32/Server.cpp	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,335 @@
+// Server.cpp
+// 
+// Copyright (c) 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+// 
+// Initial Contributors:
+// Accenture - Initial contribution
+//
+
+#include "Misc.h"
+#include "stdafx.h"
+#include "console_host.h"
+#include "Server.h"
+#include "ConsoleWindow.h"
+#include "RemoteConsole.h"
+
+const int KMajorVersion = 1;
+const int KServerInitParam = ID_RC_CLOSE - 1;
+static CServer* sServer = NULL;
+LPCTSTR KServerWindowClassName = TEXT("ServerWindowClass");
+LPCTSTR KServerConsoleName = TEXT("Server Console");
+LPCTSTR KServerSocketName = TEXT("Server Socket");
+
+
+class TCreateConsoleWindowPacket
+	{
+public:
+	void Validate() const;
+public:
+	int iMajorVersion;
+	int iMinorVersion;
+	int iWidth;
+	int iHeight;
+	int iTitleLength;
+	};
+
+void TCreateConsoleWindowPacket::Validate() const
+	{
+	if (iMajorVersion > KMajorVersion)
+		{
+		throw KExceptionInvalidClientVersion;
+		}
+	}
+
+
+CServer* CServer::New(HINSTANCE aAppHandle)
+	{
+	std::auto_ptr<CServer> self(new(EThrow) CServer(aAppHandle));
+	self->Construct();
+	return self.release();
+	}
+
+CServer::~CServer()
+	{
+	delete iSocket;
+	delete iConsole;
+	}
+
+void CServer::HandleException(TException aException)
+	{
+	switch (aException)
+		{
+		case KExceptionNoMemory:
+			iConsole->Write(TEXT("Out of memory\r\n"));
+			break;
+		case KExceptionWindowConstructFailed:
+			iConsole->Write(TEXT("Failed to construct new window\r\n"));
+			break;
+		case KExceptionConsoleWindowConstructFailed:
+			iConsole->Write(TEXT("Failed to construct new console window\r\n"));
+			break;
+		case KExceptionSocketConstructFailed:
+			iConsole->Write(TEXT("Failed to construct new socket\r\n"));
+			break;
+		case KExceptionSocketBindFailed:
+			iConsole->Write(TEXT("Failed to bind server socket. Is something else already listening on that port?\r\n"));
+			break;
+		case KExceptionSocketListenFailed:
+			iConsole->Write(TEXT("Failed to listen on server socket\r\n"));
+			break;
+		case KExceptionSocketSelectFailed:
+			iConsole->Write(TEXT("Failed to asynchronously wait on socket\r\n"));
+			break;
+		case KExceptionSocketAcceptFailed:
+			iConsole->Write(TEXT("Failed to accept to client connection\r\n"));
+			break;
+		case KExceptionSocketReadFailed:
+			iConsole->Write(TEXT("Failed to read from socket\r\n"));
+			break;
+		case KExceptionInvalidClientVersion:
+			iConsole->Write(TEXT("Invalid client version\r\n"));
+			break;
+		case KExceptionFailedToWritePrefsFile:
+			iConsole->Write(TEXT("Failed to write preferences file\r\n"));
+			break;
+		default:
+			iConsole->Write(TEXT("Unknown error\r\n"));
+			break;
+		}
+	}
+
+TPreferences& CServer::Preferences()
+	{
+	return iPreferences;
+	}
+
+const TPreferences& CServer::Preferences() const
+	{
+	return iPreferences;
+	}
+
+CServer::CServer(HINSTANCE aAppHandle) : iAppHandle(aAppHandle), iSocket(NULL), iConsole(NULL), iPort(0)
+	{
+	sServer = this;
+	}
+
+void CServer::Construct()
+	{
+	WNDCLASSEX wcex;
+	wcex.cbSize = sizeof(WNDCLASSEX); 
+	wcex.style			= CS_HREDRAW | CS_VREDRAW;
+	wcex.lpfnWndProc	= (WNDPROC)CWindow::HandleMessage;
+	wcex.cbClsExtra		= 0;
+	wcex.cbWndExtra		= 0;
+	wcex.hInstance		= iAppHandle;
+	wcex.hIcon			= LoadIcon(iAppHandle, (LPCTSTR)IDI_CONSOLE_HOST);
+	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
+	wcex.hbrBackground	= NULL;
+	wcex.lpszMenuName	= (LPCTSTR)ID_SERVER_MENU;
+	wcex.lpszClassName	= KServerWindowClassName;
+	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
+	if (RegisterClassEx(&wcex) == 0)
+		{
+		throw KExceptionWindowClassRegistrationFailed;
+		}
+	
+	iConsole = CConsoleWindow::New(iAppHandle, KServerWindowClassName, TEXT("Remote Console Server"), CW_USEDEFAULT, CW_USEDEFAULT, 40, 20, 20, this, NULL, TRUE);
+	iConsole->SetName(KServerConsoleName);
+
+	try
+		{
+		iPreferences.Read();
+		}
+	catch (...)
+		{
+		iConsole->Write(TEXT("Unable to read preferences"));
+		}
+
+	iSocket = CServerSocket::New(*iConsole);
+	iSocket->SetName(KServerSocketName);
+	PostMessage(iConsole->Handle(), WM_COMMAND, KServerInitParam, 0);
+	}
+
+void CServer::Listen()
+	{
+	if (iPort != iPreferences.ServerPort())
+		{
+		delete iSocket;
+		iSocket = CServerSocket::New(*iConsole);
+		iSocket->SetName(KServerSocketName);
+		iSocket->Listen(iPreferences.ServerPort(), 5, *this);
+		iConsole->WriteFormat(TEXT("Listening on port %d\r\n"), iPreferences.ServerPort());
+		iPort = iPreferences.ServerPort();
+		}
+	}
+
+void CServer::HandleNewClient(CClientSocket& aClientSocket)
+	{
+	CSocketCommandReader* commandReader = CSocketCommandReader::New(aClientSocket, *this);
+	commandReader->ReadCommand();
+	}
+
+void CServer::HandleSocketClosure(CSocket& aSocket)
+	{
+	ASSERT(&aSocket == iSocket);
+	PostQuitMessage(0);
+	}
+
+void CServer::HandleSocketCommand(TPacketHeader::TPacketType aCommand, const char* aPacket, int aPacketLength, CSocketCommandReader& aReader)
+	{
+	switch (aCommand)
+		{
+		case TPacketHeader::ECommandCreateConsoleWindow:
+			{
+			iConsole->Write(TEXT("Creating new console window...\r\n"));
+			const TCreateConsoleWindowPacket* createConsoleWindowPacket = new((char*)aPacket) TCreateConsoleWindowPacket;
+			LPTSTR title = (TCHAR*)((char*)aPacket + sizeof(TCreateConsoleWindowPacket));
+			try
+				{
+				createConsoleWindowPacket->Validate();
+				CRemoteConsole* remoteConsole = CRemoteConsole::New(iAppHandle, aReader, title, createConsoleWindowPacket->iWidth, createConsoleWindowPacket->iHeight, iPreferences);
+				int consoleId = remoteConsole->Id();
+				iConsole->WriteFormat(TEXT("Created window \"%s\" (%d)...\r\n"), title, consoleId);
+				aReader.SendResponse((char*)&consoleId, sizeof(int));
+				}
+			catch (TException aException)
+				{
+				int err = -2; // KErrGeneral.
+				if (aException == KExceptionInvalidClientVersion)
+					{
+					err = -21; // KErrAccessDenied.
+					}
+				aReader.SendResponse((char*)&err, sizeof(int));
+				delete &aReader;
+				throw aException;
+				}
+			catch (...)
+				{
+				delete &aReader;
+				throw KExceptionUnknown;
+				}
+			break;
+			}
+		case TPacketHeader::ECommandAttachKeyEventSocket:
+			{
+			iConsole->Write(TEXT("Attaching key event socket...\r\n"));
+			int* consoleId = new((char*)aPacket) int;
+			CRemoteConsole* remoteConsole = CRemoteConsole::Instance(*consoleId);
+			if (remoteConsole)
+				{
+				remoteConsole->AttachKeyEventSocket(aReader.ReleaseSocket());
+				iConsole->WriteFormat(TEXT("Attached key event socket to window %d...\r\n"), *consoleId);
+				}
+			delete &aReader;
+			break;
+			}
+		default:
+			{
+			iConsole->WriteFormat(TEXT("Invalid server socket command: %d\r\n"), aCommand);
+			delete &aReader;
+			break;
+			}
+		}
+	}
+
+void CServer::HandleSocketClosure(CSocketCommandReader& aReader)
+	{
+	delete &aReader;
+	}
+
+void CServer::HandleWindowClosure(CWindow& aWindow)
+	{
+	ASSERT(&aWindow == iConsole);
+	PostQuitMessage(0);
+	}
+
+LRESULT CALLBACK PrefsCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+	{
+	switch (message)
+		{
+		case WM_INITDIALOG:
+			TCHAR string[128];
+			swprintf(string, TEXT("%u"), sServer->Preferences().ServerPort());
+			SetDlgItemText(hDlg, ID_EDIT_PORT, string);
+			swprintf(string, TEXT("%u"), sServer->Preferences().DefaultWindowWidth());
+			SetDlgItemText(hDlg, ID_EDIT_WIN_WIDTH, string);
+			swprintf(string, TEXT("%u"), sServer->Preferences().DefaultWindowHeight());
+			SetDlgItemText(hDlg, ID_EDIT_WIN_HEIGHT, string);
+			swprintf(string, TEXT("%u"), sServer->Preferences().DefaultWindowPosX());
+			SetDlgItemText(hDlg, ID_EDIT_WIN_POS_X, string);
+			swprintf(string, TEXT("%u"), sServer->Preferences().DefaultWindowPosY());
+			SetDlgItemText(hDlg, ID_EDIT_WIN_POS_Y, string);
+			EnableWindow(GetDlgItem(hDlg, ID_EDIT_WIN_POS_X), !sServer->Preferences().SystemPositionedWindows());
+			EnableWindow(GetDlgItem(hDlg, ID_EDIT_WIN_POS_Y), !sServer->Preferences().SystemPositionedWindows());
+			CheckDlgButton(hDlg, ID_CHECK_WIN_POS, sServer->Preferences().SystemPositionedWindows());
+			swprintf(string, TEXT("%u"), sServer->Preferences().NumOverflowLines());
+			SetDlgItemText(hDlg, ID_OVERFLOW_LINES, string);
+			return TRUE;
+		case WM_COMMAND:
+			switch (LOWORD(wParam))
+				{
+				case IDOK:
+					{
+					TCHAR string[128];
+					GetDlgItemText(hDlg, ID_EDIT_PORT, string, 128);
+					unsigned int val;
+					swscanf(string, TEXT("%u"), &val);
+					sServer->Preferences().SetServerPort((unsigned short)val);
+					GetDlgItemText(hDlg, ID_EDIT_WIN_WIDTH, string, 128);
+					swscanf(string, TEXT("%u"), &val);
+					sServer->Preferences().SetDefaultWindowWidth(val);
+					GetDlgItemText(hDlg, ID_EDIT_WIN_HEIGHT, string, 128);
+					swscanf(string, TEXT("%u"), &val);
+					sServer->Preferences().SetDefaultWindowHeight(val);
+					GetDlgItemText(hDlg, ID_EDIT_WIN_POS_X, string, 128);
+					swscanf(string, TEXT("%u"), &val);
+					sServer->Preferences().SetDefaultWindowPosX(val);
+					GetDlgItemText(hDlg, ID_EDIT_WIN_POS_Y, string, 128);
+					swscanf(string, TEXT("%u"), &val);
+					sServer->Preferences().SetDefaultWindowPosY(val);
+					GetDlgItemText(hDlg, ID_OVERFLOW_LINES, string, 128);
+					swscanf(string, TEXT("%u"), &val);
+					sServer->Preferences().SetNumOverflowLines(val);
+					sServer->Preferences().SetSystemPositionedWindows((IsDlgButtonChecked(hDlg, ID_CHECK_WIN_POS) == BST_CHECKED) ? TRUE : FALSE);
+					sServer->Preferences().Write();
+					sServer->Listen();
+					}	// Deliberate fall through.
+				case IDCANCEL:
+					{
+					EndDialog(hDlg, LOWORD(wParam));
+					return TRUE;
+					}
+				case ID_CHECK_WIN_POS:
+					{
+					int isChecked = IsDlgButtonChecked(hDlg, ID_CHECK_WIN_POS);
+					EnableWindow(GetDlgItem(hDlg, ID_EDIT_WIN_POS_X), !isChecked);
+					EnableWindow(GetDlgItem(hDlg, ID_EDIT_WIN_POS_Y), !isChecked);
+					break;
+					}
+				}
+			break;
+		}
+    return FALSE;
+	}
+
+LRESULT CServer::HandleWindowCommand(UINT aMessage, WPARAM aWParam, LPARAM aLParam)
+	{
+	int wmId = LOWORD(aWParam); 
+	int wmEvent = HIWORD(aWParam); 
+	switch (wmId)
+		{
+		case KServerInitParam:
+			Listen();
+			break;
+		case ID_PREFS:
+			DialogBox(iAppHandle, (LPCTSTR)IDD_PREFS_DIALOG, iConsole->Handle(), (DLGPROC)PrefsCallback);
+			break;
+		default:
+			return DefWindowProc(iConsole->Handle(), aMessage, aWParam, aLParam);
+		}
+	return 0;
+	}