plugins/consoles/rcons/client/src/remote_console.cpp
changeset 0 7f656887cf89
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // remote_console.cpp
       
     2 // 
       
     3 // Copyright (c) 2005 - 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "Eclipse Public License v1.0"
       
     6 // which accompanies this distribution, and is available
       
     7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 // 
       
     9 // Initial Contributors:
       
    10 // Accenture - Initial contribution
       
    11 //
       
    12 
       
    13 #include <e32uid.h>
       
    14 #include <in_sock.h>
       
    15 #ifdef USE_RCONNECTION
       
    16 #include <es_enum.h>
       
    17 #include <commdbconnpref.h>
       
    18 #endif
       
    19 #include <fshell/consoleextensions.h>
       
    20 #include "remote_console.h"
       
    21 
       
    22 const TInt KMajorVersion = 1;
       
    23 const TInt KMinorVersion = 0;
       
    24 
       
    25 #define DEBUG_LOG(x) if (iUnderlyingConsole && iConfig.Debug()) iUnderlyingConsole->Write(_L(x))
       
    26 #define DEBUG_LOG_1(x, a) if (iUnderlyingConsole && iConfig.Debug()) iUnderlyingConsole->Printf(_L(x), a)
       
    27 #define DEBUG_LOG_2(x, a, b) if (iUnderlyingConsole && iConfig.Debug()) iUnderlyingConsole->Printf(_L(x), a, b)
       
    28 #define DEBUG_LOG_3(x, a, b, c) if (iUnderlyingConsole && iConfig.Debug()) iUnderlyingConsole->Printf(_L(x), a, b, c)
       
    29 #define CLEANUP_AND_RETURN_IF_ERROR(x) { TInt __err = x; if (__err < 0) { CleanupConnection(); return __err; } }
       
    30 
       
    31 enum TPacketType
       
    32 	{
       
    33 	ECommandCreateConsoleWindow,
       
    34 	ECommandAttachKeyEventSocket,
       
    35 	ECommandWrite,
       
    36 	ECommandGetCursorPos,
       
    37 	ECommandSetAbsCursorPos,
       
    38 	ECommandSetRelCursorPos,
       
    39 	ECommandSetCursorHeight,
       
    40 	ECommandGetScreenSize,
       
    41 	ECommandSetTitle,
       
    42 	ECommandClearScreen,
       
    43 	ECommandClearToEndOfLine
       
    44 	};
       
    45 
       
    46 
       
    47 class THeaderBase
       
    48 	{
       
    49 public:
       
    50 	THeaderBase(TPacketType aCommand, TInt aPacketSize);
       
    51 private:
       
    52 	const TInt iPacketType;
       
    53 	const TInt iPacketSize;
       
    54 	};
       
    55 
       
    56 THeaderBase::THeaderBase(TPacketType aCommand, TInt aPacketSize)
       
    57 	: iPacketType(aCommand), iPacketSize(aPacketSize - sizeof(THeaderBase))
       
    58 	{
       
    59 	}
       
    60 
       
    61 class TCreateConsoleWindowHeader : public THeaderBase
       
    62 	{
       
    63 public:
       
    64 	TCreateConsoleWindowHeader(const TDesC& aTitle, TSize aSize);
       
    65 private:
       
    66 	const TInt iMajorVersion;
       
    67 	const TInt iMinorVersion;
       
    68 	TInt iWidth;
       
    69 	TInt iHeight;
       
    70 	TInt iTitleLength;
       
    71 	};
       
    72 
       
    73 TCreateConsoleWindowHeader::TCreateConsoleWindowHeader(const TDesC& aTitle, TSize aSize)
       
    74 	: THeaderBase(ECommandCreateConsoleWindow, sizeof(TCreateConsoleWindowHeader) + aTitle.Size()), iMajorVersion(KMajorVersion), iMinorVersion(KMinorVersion), iWidth(aSize.iWidth), iHeight(aSize.iHeight), iTitleLength(aTitle.Length())
       
    75 	{
       
    76 	}
       
    77 
       
    78 class TAttachKeyEventSocketHeader : public THeaderBase
       
    79 	{
       
    80 public:
       
    81 	TAttachKeyEventSocketHeader(TInt aWindowId);
       
    82 private:
       
    83 	TInt iWindowId;
       
    84 	};
       
    85 
       
    86 TAttachKeyEventSocketHeader::TAttachKeyEventSocketHeader(TInt aWindowId)
       
    87 	: THeaderBase(ECommandAttachKeyEventSocket, sizeof(TAttachKeyEventSocketHeader)), iWindowId(aWindowId)
       
    88 	{
       
    89 	}
       
    90 
       
    91 class TWriteHeader : public THeaderBase
       
    92 	{
       
    93 public:
       
    94 	TWriteHeader(const TDesC& aDes);
       
    95 private:
       
    96 	TInt iDesLength;
       
    97 	};
       
    98 
       
    99 TWriteHeader::TWriteHeader(const TDesC& aDes)
       
   100 	: THeaderBase(ECommandWrite, sizeof(TWriteHeader) + aDes.Size()), iDesLength(aDes.Length())
       
   101 	{
       
   102 	}
       
   103 
       
   104 class TWriteOneHeader : public THeaderBase
       
   105 	{
       
   106 public:
       
   107 	TWriteOneHeader(const TDesC& aDes);
       
   108 private:
       
   109 	TInt iDesLength;
       
   110 	TUint16 iChar;
       
   111 	};
       
   112 
       
   113 TWriteOneHeader::TWriteOneHeader(const TDesC& aDes)
       
   114 	: THeaderBase(ECommandWrite, sizeof(TWriteOneHeader)), iDesLength(1), iChar(aDes[0])
       
   115 	{
       
   116 	}
       
   117 
       
   118 
       
   119 class TSetCursorPosHeader : public THeaderBase
       
   120 	{
       
   121 public:
       
   122 	TSetCursorPosHeader(TPacketType aCommand, const TPoint& aPos);
       
   123 private:
       
   124 	TInt iX;
       
   125 	TInt iY;
       
   126 	};
       
   127 
       
   128 TSetCursorPosHeader::TSetCursorPosHeader(TPacketType aCommand, const TPoint& aPos)
       
   129 	: THeaderBase(aCommand, sizeof(TSetCursorPosHeader)), iX(aPos.iX), iY(aPos.iY)
       
   130 	{
       
   131 	ASSERT((aCommand == ECommandSetAbsCursorPos) || (aCommand == ECommandSetRelCursorPos));
       
   132 	}
       
   133 
       
   134 class TSetCursorHeightHeader : public THeaderBase
       
   135 	{
       
   136 public:
       
   137 	TSetCursorHeightHeader(TInt aHeight);
       
   138 private:
       
   139 	TInt iHeight;
       
   140 	};
       
   141 
       
   142 TSetCursorHeightHeader::TSetCursorHeightHeader(TInt aHeight)
       
   143 	: THeaderBase(ECommandSetCursorHeight, sizeof(TSetCursorHeightHeader)), iHeight(aHeight)
       
   144 	{
       
   145 	}
       
   146 
       
   147 class TSetTitleHeader : public THeaderBase
       
   148 	{
       
   149 public:
       
   150 	TSetTitleHeader(const TDesC& aTitle);
       
   151 	};
       
   152 
       
   153 TSetTitleHeader::TSetTitleHeader(const TDesC& aTitle)
       
   154 	: THeaderBase(ECommandSetTitle, sizeof(TSetTitleHeader) + aTitle.Size())
       
   155 	{
       
   156 	}
       
   157 
       
   158 
       
   159 CRemoteConsole::CRemoteConsole()
       
   160 	: iKeyEventPckg(iKeyEvent)
       
   161 	{
       
   162 	}
       
   163 
       
   164 CRemoteConsole::~CRemoteConsole()
       
   165 	{
       
   166 	CleanupConnection();
       
   167 	delete iUnderlyingConsole;
       
   168 	}
       
   169 
       
   170 TInt CRemoteConsole::Create(const TDesC& aTitle, TSize aSize)
       
   171 	{
       
   172 	TInt ret = iConfig.Init();
       
   173 	if (ret == KErrNone)
       
   174 		{
       
   175 		ret = Connect(aTitle, aSize);
       
   176 		}
       
   177 	if (ret && iUnderlyingConsole)
       
   178 		{
       
   179 		iUnderlyingConsole->Printf(_L("Remote connection failed: %d\r\n"), ret);
       
   180 #ifdef __WINS__
       
   181 		// Give the user the chance to read the error message.
       
   182 		User::After(10000000);
       
   183 #endif
       
   184 		}
       
   185 	return ret;
       
   186 	}
       
   187 
       
   188 TInt CRemoteConsole::Connect(const TDesC& aTitle, TSize aSize)
       
   189 	{
       
   190 	// Connect to Socket Server.
       
   191 	DEBUG_LOG("Connecting to ESock\r\n");
       
   192 	TInt err = iSocketSession.Connect();
       
   193 	CLEANUP_AND_RETURN_IF_ERROR(err);
       
   194 
       
   195 #ifdef USE_RCONNECTION
       
   196 	switch (iConfig.ConnectionType())
       
   197 		{
       
   198 		default:
       
   199 		case TRemoteConsoleConfig::EImplicit:
       
   200 			{
       
   201 			DEBUG_LOG("Opening command socket\r\n");
       
   202 			CLEANUP_AND_RETURN_IF_ERROR(iCommandSocket.Open(iSocketSession, KAfInet, KSockStream, iConfig.Protocol()));
       
   203 			DEBUG_LOG("Opening event\r\n");
       
   204 			CLEANUP_AND_RETURN_IF_ERROR(iKeyEventSocket.Open(iSocketSession, KAfInet, KSockStream, iConfig.Protocol()));
       
   205 			break;
       
   206 			}
       
   207 		case TRemoteConsoleConfig::EExplicit:
       
   208 			{
       
   209 			DEBUG_LOG("Opening connection\r\n");
       
   210 			CLEANUP_AND_RETURN_IF_ERROR(iConnection.Open(iSocketSession));
       
   211 			TUint numConnections;
       
   212 			DEBUG_LOG("Enumerating existing connections\r\n");
       
   213 			err = iConnection.EnumerateConnections(numConnections);
       
   214 			CLEANUP_AND_RETURN_IF_ERROR(err);
       
   215 			DEBUG_LOG_2("Looking for IapId: %d NetId: %d\r\n", iConfig.IapId(), iConfig.NetworkId());
       
   216 
       
   217 			TBool connectionAttached(EFalse);
       
   218 			for (TInt i = 1; i <= (TInt)numConnections; ++i)
       
   219 				{
       
   220 				DEBUG_LOG_1("Getting info for connection %d\r\n", i);
       
   221 				TConnectionInfoBuf connectionInfoBuf;
       
   222 				CLEANUP_AND_RETURN_IF_ERROR(iConnection.GetConnectionInfo(i, connectionInfoBuf));
       
   223 				const TConnectionInfo& info = connectionInfoBuf();
       
   224 				DEBUG_LOG_2("Found IapId: %d NetId: %d\r\n", info.iIapId, info.iNetId);
       
   225 				if ((info.iIapId == iConfig.IapId()) && (info.iNetId == iConfig.NetworkId()))
       
   226 					{
       
   227 					DEBUG_LOG("Matching IAP and Network IDs found, attaching...\r\n");
       
   228 					CLEANUP_AND_RETURN_IF_ERROR(iConnection.Attach(connectionInfoBuf, RConnection::EAttachTypeNormal));
       
   229 					DEBUG_LOG("Opening command socket on connection\r\n");
       
   230 					CLEANUP_AND_RETURN_IF_ERROR(iCommandSocket.Open(iSocketSession, KAfInet, KSockStream, iConfig.Protocol(), iConnection));
       
   231 					DEBUG_LOG("Opening event socket on connection\r\n");
       
   232 					CLEANUP_AND_RETURN_IF_ERROR(iKeyEventSocket.Open(iSocketSession, KAfInet, KSockStream, iConfig.Protocol(), iConnection));
       
   233 					connectionAttached = ETrue;
       
   234 					}
       
   235 				}
       
   236 			if (!connectionAttached)
       
   237 				{
       
   238 				CLEANUP_AND_RETURN_IF_ERROR(KErrCouldNotConnect);
       
   239 				}
       
   240 			break;
       
   241 			}
       
   242 		}
       
   243 #else	// USE_RCONNECTION
       
   244 	DEBUG_LOG("Opening command socket\r\n");
       
   245 	CLEANUP_AND_RETURN_IF_ERROR(iCommandSocket.Open(iSocketSession, KAfInet, KSockStream, iConfig.Protocol()));
       
   246 	DEBUG_LOG("Opening event\r\n");
       
   247 	CLEANUP_AND_RETURN_IF_ERROR(iKeyEventSocket.Open(iSocketSession, KAfInet, KSockStream, iConfig.Protocol()));
       
   248 #endif
       
   249 
       
   250 	iCommandSocket.SetOpt(KSoTcpNoDelay, KSolInetTcp, ETrue);	// Ignore error (may not be supported).
       
   251 	iKeyEventSocket.SetOpt(KSoTcpNoDelay, KSolInetTcp, ETrue);	// Ignore error (may not be supported).
       
   252 
       
   253 	// Resolve IP address (if need be).
       
   254 	const TDesC& remoteHostName = iConfig.RemoteHostName();
       
   255 	TInetAddr remoteAddress(iConfig.RemotePort());
       
   256 	err = remoteAddress.Input(remoteHostName);
       
   257 	if (err)
       
   258 		{
       
   259 		RHostResolver resolver;
       
   260 #ifdef USE_RCONNECTION
       
   261 		if (iConnection.SubSessionHandle())
       
   262 			{
       
   263 			CLEANUP_AND_RETURN_IF_ERROR(resolver.Open(iSocketSession, KAfInet, iConfig.Protocol(), iConnection));
       
   264 			}
       
   265 		else
       
   266 			{
       
   267 			CLEANUP_AND_RETURN_IF_ERROR(resolver.Open(iSocketSession, KAfInet, iConfig.Protocol()));
       
   268 			}
       
   269 #else
       
   270 		CLEANUP_AND_RETURN_IF_ERROR(resolver.Open(iSocketSession, KAfInet, iConfig.Protocol()));
       
   271 #endif
       
   272 		TNameEntry nameEntry;
       
   273 		err = resolver.GetByName(remoteHostName, nameEntry);
       
   274 		if (err)
       
   275 			{
       
   276 			resolver.Close();
       
   277 			CLEANUP_AND_RETURN_IF_ERROR(err);
       
   278 			}
       
   279 		remoteAddress.SetAddress(TInetAddr::Cast(nameEntry().iAddr).Address());
       
   280 		resolver.Close();
       
   281 		}
       
   282 
       
   283 	// Connect command socket.
       
   284 	DEBUG_LOG_2("Connecting command socket to %S : %d\r\n", &remoteHostName, iConfig.RemotePort());
       
   285 	TRequestStatus status;
       
   286 	iCommandSocket.Connect(remoteAddress, status);
       
   287 	User::WaitForRequest(status);
       
   288 	CLEANUP_AND_RETURN_IF_ERROR(status.Int());
       
   289 
       
   290 	// Request a new console window in the remote host.
       
   291 	DEBUG_LOG("Requesting new console window\r\n");
       
   292 	TCreateConsoleWindowHeader createConsoleWindowHeader(aTitle, aSize);
       
   293 	TPckgC<TCreateConsoleWindowHeader> createConsoleWindowHeaderPckg(createConsoleWindowHeader);
       
   294 	iCommandSocket.Write(createConsoleWindowHeaderPckg, status);
       
   295 	User::WaitForRequest(status);
       
   296 	CLEANUP_AND_RETURN_IF_ERROR(status.Int());
       
   297 	DEBUG_LOG("Sending title\r\n");
       
   298 	TPtrC8 narrowTitlePtr((TUint8*)aTitle.Ptr(), aTitle.Size());
       
   299 	iCommandSocket.Write(narrowTitlePtr, status);
       
   300 	User::WaitForRequest(status);
       
   301 	CLEANUP_AND_RETURN_IF_ERROR(status.Int());
       
   302 
       
   303 	// Read response (window identifier if successful).
       
   304 	DEBUG_LOG("Reading window identifier\r\n");
       
   305 	TInt response;
       
   306 	TPckg<TInt> responsePckg(response);
       
   307 	iCommandSocket.Read(responsePckg, status);
       
   308 	User::WaitForRequest(status);
       
   309 	CLEANUP_AND_RETURN_IF_ERROR(status.Int());
       
   310 	CLEANUP_AND_RETURN_IF_ERROR(response);
       
   311 
       
   312 	// Connect key event socket.
       
   313 	DEBUG_LOG_2("Connecting event socket to %S : %d\r\n", &remoteHostName, iConfig.RemotePort());
       
   314 	iKeyEventSocket.Connect(remoteAddress, status);
       
   315 	User::WaitForRequest(status);
       
   316 	CLEANUP_AND_RETURN_IF_ERROR(status.Int());
       
   317 
       
   318 	// Attach key event socket to the new console window.
       
   319 	DEBUG_LOG("Attaching event socket to console window\r\n");
       
   320 	TAttachKeyEventSocketHeader attachKeyEventSocketHeader(response);
       
   321 	TPckgC<TAttachKeyEventSocketHeader> attachKeyEventSocketHeaderPckg(attachKeyEventSocketHeader);
       
   322 	iKeyEventSocket.Write(attachKeyEventSocketHeaderPckg, status);
       
   323 	User::WaitForRequest(status);
       
   324 	CLEANUP_AND_RETURN_IF_ERROR(status.Int());
       
   325 
       
   326 	return KErrNone;
       
   327 	}
       
   328 
       
   329 void CRemoteConsole::Read(TRequestStatus& aStatus)
       
   330 	{
       
   331 	iKeyEventSocket.Read(iKeyEventPckg, aStatus);
       
   332 	}
       
   333 
       
   334 void CRemoteConsole::ReadCancel()
       
   335 	{
       
   336 	iKeyEventSocket.CancelRead();
       
   337 	}
       
   338 
       
   339 void CRemoteConsole::Write(const TDesC& aDes)
       
   340 	{
       
   341 	if (aDes.Length() == 1)
       
   342 		{
       
   343 		// Only do a single ESock write for the case where there's only 1 character.
       
   344 		TWriteOneHeader writeHeader(aDes);
       
   345 		TPckgC<TWriteOneHeader> writeHeaderPckg(writeHeader);
       
   346 		WriteCommand(writeHeaderPckg);
       
   347 		}
       
   348 	else
       
   349 		{
       
   350 		TWriteHeader writeHeader(aDes);
       
   351 		TPckgC<TWriteHeader> writeHeaderPckg(writeHeader);
       
   352 		WriteCommand(writeHeaderPckg);
       
   353 		TPtrC8 narrowPtr((TUint8*)aDes.Ptr(), aDes.Size());
       
   354 		WriteCommand(narrowPtr);
       
   355 		}
       
   356 	}
       
   357 
       
   358 TPoint CRemoteConsole::CursorPos() const
       
   359 	{
       
   360 	THeaderBase header(ECommandGetCursorPos, sizeof(THeaderBase));
       
   361 	TPckgC<THeaderBase> headerPckg(header);
       
   362 	WriteCommand(headerPckg);
       
   363 	TPoint response;
       
   364 	TPckg<TPoint> responsePckg(response);
       
   365 	ReadCommandResponse(responsePckg);
       
   366 	return response;
       
   367 	}
       
   368 
       
   369 void CRemoteConsole::SetCursorPosAbs(const TPoint& aPoint)
       
   370 	{
       
   371 	TSetCursorPosHeader header(ECommandSetAbsCursorPos, aPoint);
       
   372 	TPckgC<TSetCursorPosHeader> headerPckg(header);
       
   373 	WriteCommand(headerPckg);
       
   374 	}
       
   375 
       
   376 void CRemoteConsole::SetCursorPosRel(const TPoint& aPoint)
       
   377 	{
       
   378 	TSetCursorPosHeader header(ECommandSetRelCursorPos, aPoint);
       
   379 	TPckgC<TSetCursorPosHeader> headerPckg(header);
       
   380 	WriteCommand(headerPckg);
       
   381 	}
       
   382 
       
   383 void CRemoteConsole::SetCursorHeight(TInt aPercentage)
       
   384 	{
       
   385 	TSetCursorHeightHeader header(aPercentage);
       
   386 	TPckgC<TSetCursorHeightHeader> headerPckg(header);
       
   387 	WriteCommand(headerPckg);
       
   388 	}
       
   389 
       
   390 void CRemoteConsole::SetTitle(const TDesC& aTitle)
       
   391 	{
       
   392 	TSetTitleHeader header(aTitle);
       
   393 	TPckgC<TSetTitleHeader> headerPckg(header);
       
   394 	WriteCommand(headerPckg);
       
   395 	TPtrC8 narrowTitlePtr((TUint8*)aTitle.Ptr(), aTitle.Size());
       
   396 	WriteCommand(narrowTitlePtr);
       
   397 	}
       
   398 
       
   399 void CRemoteConsole::ClearScreen()
       
   400 	{
       
   401 	THeaderBase header(ECommandClearScreen, sizeof(THeaderBase));
       
   402 	TPckgC<THeaderBase> headerPckg(header);
       
   403 	WriteCommand(headerPckg);
       
   404 	}
       
   405 
       
   406 void CRemoteConsole::ClearToEndOfLine()
       
   407 	{
       
   408 	THeaderBase header(ECommandClearToEndOfLine, sizeof(THeaderBase));
       
   409 	TPckgC<THeaderBase> headerPckg(header);
       
   410 	WriteCommand(headerPckg);
       
   411 	}
       
   412 
       
   413 TSize CRemoteConsole::ScreenSize() const
       
   414 	{
       
   415 	THeaderBase header(ECommandGetScreenSize, sizeof(THeaderBase));
       
   416 	TPckgC<THeaderBase> headerPckg(header);
       
   417 	WriteCommand(headerPckg);
       
   418 	TSize response;
       
   419 	TPckg<TSize> responsePckg(response);
       
   420 	ReadCommandResponse(responsePckg);
       
   421 	return response;
       
   422 	}
       
   423 
       
   424 TKeyCode CRemoteConsole::KeyCode() const
       
   425 	{
       
   426 	return (TKeyCode)(iKeyEvent.iChar);
       
   427 	}
       
   428 
       
   429 TUint CRemoteConsole::KeyModifiers() const
       
   430 	{
       
   431 	return iKeyEvent.iModifiers;
       
   432 	}
       
   433 
       
   434 TInt CRemoteConsole::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
       
   435 	{
       
   436 	if (aExtensionId == UnderlyingConsole::KSetUnderlyingConsoleExtension)
       
   437 		{
       
   438 		iUnderlyingConsole = (CConsoleBase*)a1;
       
   439 		return KErrNone;
       
   440 		}
       
   441 	else
       
   442 		{
       
   443 		return CConsoleBase::Extension_(aExtensionId, a0, a1);
       
   444 		}
       
   445 	}
       
   446 
       
   447 void CRemoteConsole::CleanupConnection()
       
   448 	{
       
   449 	iKeyEventSocket.Close();
       
   450 	iCommandSocket.Close();
       
   451 #ifdef USE_RCONNECTION
       
   452 	iConnection.Close();
       
   453 #endif
       
   454 	iSocketSession.Close();
       
   455 	}
       
   456 
       
   457 void CRemoteConsole::WriteCommand(const TDesC8& aDes) const
       
   458 	{
       
   459 	TRequestStatus status;
       
   460 	iCommandSocket.Write(aDes, status);
       
   461 	User::WaitForRequest(status);
       
   462 	}
       
   463 
       
   464 void CRemoteConsole::ReadCommandResponse(TDes8& aDes) const
       
   465 	{
       
   466 	TRequestStatus status;
       
   467 	iCommandSocket.Read(aDes, status);
       
   468 	User::WaitForRequest(status);
       
   469 	}
       
   470 
       
   471 
       
   472 EXPORT_C TAny* NewConsole()
       
   473 	{
       
   474 	return new CRemoteConsole;
       
   475 	}
       
   476 
       
   477 #ifndef EKA2
       
   478 GLDEF_C TInt E32Dll(TDllReason)
       
   479 	{
       
   480 	return(KErrNone);
       
   481 	}
       
   482 #endif