applayerprotocols/telnetengine/SRC/TELRESOL.CPP
changeset 0 b16258d2340f
equal deleted inserted replaced
-1:000000000000 0:b16258d2340f
       
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Telnet Protocol API
       
    15 // CTelnetResolver implementation
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file 
       
    21 */
       
    22 
       
    23 
       
    24 #include "TELRESOL.H"
       
    25 #include "IOBUFFER.H"
       
    26 #include "TELCTRL.H"
       
    27 #include "ACTIVEIO.H"
       
    28 #include "TELDEBUG.H"
       
    29 
       
    30 
       
    31 CTelnetResolver::CTelnetResolver() : CActive(EPriorityStandard)
       
    32 /**
       
    33 Constructor
       
    34 */
       
    35     {
       
    36     CActiveScheduler::Add(this);
       
    37     }
       
    38 
       
    39 CTelnetResolver::~CTelnetResolver()
       
    40 /**
       
    41 Destructor
       
    42 */
       
    43     {
       
    44 	__FLOG_STATIC(KTelnetLoggingCompnt(),KTelnetLoggingTag(),_L("CTelnetResolver::D'Tor"));
       
    45 	iSocket.Close();
       
    46 	iResolver.Close();
       
    47     iSocketServ.Close();
       
    48 	Cancel();
       
    49     }
       
    50 
       
    51 CTelnetResolver* CTelnetResolver::NewL(MTelnetResolver* aNotifier)
       
    52     {
       
    53     CTelnetResolver* self = new(ELeave) CTelnetResolver;
       
    54     CleanupStack::PushL(self);
       
    55     self->ConstructL(aNotifier);
       
    56     CleanupStack::Pop();
       
    57     return self;
       
    58     }
       
    59 
       
    60 void CTelnetResolver::ConstructL(MTelnetResolver* aNotifier)
       
    61     {
       
    62     iState = EDisconnected;
       
    63 	iEvent = ENone;
       
    64 
       
    65     User::LeaveIfError(iSocketServ.Connect());
       
    66 
       
    67     iNotify = aNotifier;
       
    68     }
       
    69 
       
    70 void CTelnetResolver::TriggerActive(const TEvent aEvent)
       
    71 /**
       
    72 Helper method that triggers our active object RunL() and sets the cause
       
    73 iEvent member which is interrogated in RunL() in the appropriate state
       
    74 Currently NOT called from RunL() it'self
       
    75 */
       
    76 	{
       
    77 	iEvent = aEvent;
       
    78 	SetActive();
       
    79 	TRequestStatus *pS=&iStatus;
       
    80 	User::RequestComplete(pS,KErrNone);
       
    81 	}
       
    82 
       
    83 TInt CTelnetResolver::IssueConnect(const TDesC& aServerName, TUint aPort)
       
    84 /**
       
    85 Called as a result of an API Connect.
       
    86 Needs to use name resolution
       
    87 */
       
    88 
       
    89 	{
       
    90 	// Check for valid state
       
    91 	if(iState != EDisconnected)
       
    92 		return(KErrInUse);
       
    93 	// Set member variable for the host name and the port
       
    94     TInt err;
       
    95 	if((err = iResolver.Open(iSocketServ, KAfInet, KProtocolInetTcp)) != KErrNone)
       
    96 		return(err);
       
    97 	
       
    98 	// Copy host name and port into our object
       
    99 	iHostAddr.SetPort(aPort);
       
   100 	iServerName = aServerName;
       
   101 	// Make the async call to the resolver
       
   102 	iResolver.GetByName(iServerName,iNameEntry,iStatus);
       
   103 	// EDisconnected is the top of the state machine so set the state for Event() completion
       
   104 	iState = ELookingUp;
       
   105 	
       
   106 	SetActive();
       
   107 	return(KErrNone);
       
   108 	}
       
   109 
       
   110 TInt CTelnetResolver::IssueConnect(const TInetAddr& aInetAddr, TUint aPort)
       
   111 /**
       
   112 Called as a result of an API Connect.
       
   113 IP address supplied
       
   114 */
       
   115 	{
       
   116 	if(iState != EDisconnected)
       
   117 		return(KErrInUse);
       
   118 
       
   119 	// copy IP and port to our object
       
   120 	iHostAddr.SetPort(aPort);
       
   121 	if (aInetAddr.Family() == KAfInet)
       
   122 		iHostAddr.SetAddress(aInetAddr.Address());
       
   123 	else
       
   124 		iHostAddr.SetAddress(aInetAddr.Ip6Address());
       
   125 
       
   126 	// Synchronous Open followed by Asynchronous Connect
       
   127 	TInt err;
       
   128 	if((err = iSocket.Open(iSocketServ, KAfInet, KSockStream, KProtocolInetTcp)) == KErrNone)
       
   129 		{
       
   130 		iSocket.Connect(iHostAddr, iStatus);
       
   131 		// EDisconnected is top of the state machine so set the state for Event() completion
       
   132 		iState = EConnecting;
       
   133 		SetActive();
       
   134 		}
       
   135 	else
       
   136 		{
       
   137 		return(err);
       
   138 		}
       
   139 
       
   140 	return(KErrNone);
       
   141 	}
       
   142 
       
   143 TInt CTelnetResolver::IssueDisconnect()
       
   144 /**
       
   145 Called as a result of API Disconnect
       
   146 */
       
   147 	{
       
   148 	TInt ret;
       
   149 	if(iState == EConnected)
       
   150 		{
       
   151 		// Requires action in the state machine so trigger RunL with the appropriate event
       
   152 		// providing the we are connected.
       
   153 		TriggerActive(EDoDisconnect);
       
   154 		ret = KErrNone;
       
   155 		}
       
   156 	else if(iState == ELookingUp)
       
   157 		{
       
   158 		// Still looking up, cancel and reset states
       
   159 		iResolver.Cancel();
       
   160 		iResolver.Close();
       
   161 		iState = EDisconnected;
       
   162 		iEvent = ENone;
       
   163 		ret = KErrServerBusy;
       
   164 		__FLOG_STATIC(KTelnetLoggingCompnt(),KTelnetLoggingTag(),_L("CTelnetResolver::IssueDisconnect() Cancel ELookingUp"));
       
   165 		}
       
   166 	else if(iState == EConnecting)
       
   167 		{
       
   168 		// Opening the socket, cancel and reset states
       
   169 		iState = EDisconnected;
       
   170 		iEvent = ENone;
       
   171 		iSocket.Close();
       
   172 		ret = KErrServerBusy;
       
   173 		__FLOG_STATIC(KTelnetLoggingCompnt(),KTelnetLoggingTag(),_L("CTelnetResolver::IssueDisconnect() Cancel EConnecting"));
       
   174 		}
       
   175 	else
       
   176 		// Already Disconnecting
       
   177 		ret = KErrDisconnected;
       
   178 
       
   179 	return(ret);
       
   180 	}
       
   181 
       
   182 void CTelnetResolver::HandleEof()
       
   183 /**
       
   184 Called from FSM when it reads Eof
       
   185 */
       
   186 	{
       
   187 	// Requires action in the state machine so trigger RunL with the appropriate event
       
   188 	TriggerActive(EEofDetected);
       
   189 	}
       
   190 
       
   191 
       
   192 void CTelnetResolver::DoCancel()
       
   193     {
       
   194     }
       
   195 
       
   196 void CTelnetResolver::RunL()
       
   197     {
       
   198 	// ONLY called from here
       
   199 	Event();
       
   200     }
       
   201 
       
   202 void CTelnetResolver::Event()
       
   203 /**
       
   204 State machine for the Telnet Resolver class.
       
   205 Called ONLY from CTelnetResolver::RunL()
       
   206 Main switch on the current state with checks for iEvent and/or iStatus depending on the state.
       
   207 EDisconnected state is not in the machine as iState is ALWAYS set to ELookingUp or EConnecting
       
   208 as a result of a client app connect request.
       
   209 TODO Need to implement client app EDoDisconnect event in the EConnecting and ELookingUp states 
       
   210 */
       
   211 	{
       
   212 	// Switch on the state. Only certain events are legal in certain states
       
   213 	switch(iState)
       
   214 		{
       
   215 	case	ELookingUp	:		
       
   216 		__FLOG_STATIC(KTelnetLoggingCompnt(),KTelnetLoggingTag(),_L("CTelnetResolver::Event() ELookingUp"));
       
   217 		// COMPLETION from host lookup (transitory state)
       
   218 		// Finished with the resolver
       
   219 		iResolver.Close();		
       
   220 		// Completion of GetByName()
       
   221 		if(iStatus == KErrNone)
       
   222 			{
       
   223 			// Get the first IP address from the list returned and copy it to our object
       
   224 			iNameRecord = iNameEntry();
       
   225 			if (TInetAddr::Cast(iNameRecord.iAddr).Family() == KAfInet)
       
   226 				iHostAddr.SetAddress(TInetAddr::Cast(iNameRecord.iAddr).Address());
       
   227 			else
       
   228 				iHostAddr.SetAddress(TInetAddr::Cast(iNameRecord.iAddr).Ip6Address());
       
   229 
       
   230 			// Get a socket and make async connection call
       
   231 			if(iSocket.Open(iSocketServ, KAfInet, KSockStream, KProtocolInetTcp) == KErrNone)
       
   232 				{
       
   233 				iSocket.Connect(iHostAddr, iStatus);
       
   234 				iState = EConnecting;
       
   235 				SetActive();
       
   236 				}				
       
   237 			else
       
   238 				{
       
   239 				// ERROR
       
   240 				__FLOG_STATIC(KTelnetLoggingCompnt(),KTelnetLoggingTag(),_L("CTelnetResolver::Event() ELookingUp ERROR 1"));
       
   241 				iState = EDisconnected;
       
   242 				iEvent = ENone;
       
   243 				iNotify->ResolverDisconnected();
       
   244 				}
       
   245 			}
       
   246 		else
       
   247 			{
       
   248 			__FLOG_STATIC(KTelnetLoggingCompnt(),KTelnetLoggingTag(),_L("CTelnetResolver::Event() ELookingUp ERROR 2"));
       
   249 			iState = EDisconnected;
       
   250 			iEvent = ENone;
       
   251 			iNotify->ResolverDisconnected();
       
   252 			}
       
   253 		break;
       
   254 								
       
   255 	case	EConnecting	:
       
   256 		__FLOG_STATIC(KTelnetLoggingCompnt(),KTelnetLoggingTag(),_L("CTelnetResolver::Event() EConnecting"));
       
   257 		// COMPLETION from Connect (Transitory state)
       
   258 		// TODO :- check iEvent for client EDoDisconnect
       
   259 		// Just check the iStatus, the event code is not relevant
       
   260 		if(iStatus == KErrNone)
       
   261 			{
       
   262 			// set the state and notify client we have connected
       
   263 			iState = EConnected;
       
   264 			TRAPD(err, iNotify->ResolverConnectedL());
       
   265 			if(err!=KErrNone)
       
   266 				{
       
   267 				__FLOG_STATIC1(KTelnetLoggingCompnt(),KTelnetLoggingTag(),_L("CTelnetResolver::Event() EConnecting, ResolverConnectedL left with error = %d"),err);	
       
   268 				iState = EDisconnected;
       
   269 				iEvent = ENone;
       
   270 				iSocket.Close();
       
   271 				iNotify->ResolverDisconnected();
       
   272 				break;
       
   273 				}
       
   274 			}
       
   275 		else
       
   276 			{
       
   277 			// ERROR
       
   278 			__FLOG_STATIC1(KTelnetLoggingCompnt(),KTelnetLoggingTag(),_L("CTelnetResolver::Event() EConnecting ERROR = %d"),iStatus.Int());
       
   279 			iState = EDisconnected;
       
   280 			iEvent = ENone;
       
   281 			iSocket.Close();
       
   282 			iNotify->ResolverDisconnected();
       
   283 			}
       
   284 		break;
       
   285 				
       
   286 	case	EConnected	:
       
   287 		// ONLY NON transitory state
       
   288 		// from the client app
       
   289 		if(iEvent == EEofDetected)
       
   290 			{
       
   291 			// EOF from the line as a result of a Read (TCP connection being closed by remote end)
       
   292 			// Reset the state, close the socket and notify the client app
       
   293 			iState = EDisconnected;
       
   294 			iEvent = ENone;
       
   295 			iSocket.Close();
       
   296 			iNotify->ResolverDisconnected();
       
   297 			}
       
   298 		else if(iEvent == EDoDisconnect)
       
   299 			{
       
   300 			// Client requested Disconnect
       
   301 			// Shutdown output (Sends TCP FIN) , set the state
       
   302 			// Asynchronous call
       
   303 			iEvent = ENone;
       
   304 			iSocket.Shutdown(RSocket::EStopOutput,iStatus);
       
   305 			iState = EShuttingDown;
       
   306 			SetActive();
       
   307 			}
       
   308 		else
       
   309 			{
       
   310 			// ERROR
       
   311 			// BUG only transition here is on the above 2 events
       
   312 			__FLOG_STATIC(KTelnetLoggingCompnt(),KTelnetLoggingTag(),_L("CTelnetResolver::Event() EConnected ERROR"));
       
   313 
       
   314 			}
       
   315 
       
   316 		break;
       
   317 
       
   318 	case	EShuttingDown	:
       
   319 		if(iStatus != KErrNone)
       
   320 			{
       
   321 			}
       
   322 		iState = EDisconnecting;
       
   323 		break;
       
   324 
       
   325 	case	EDisconnecting	:
       
   326 		// COMPLETION from client DoDisconnect shuddown()
       
   327 		// EOF from the line is all we can expect here
       
   328 		if(iEvent == EEofDetected)
       
   329 			{
       
   330 			iState = EDisconnected;
       
   331 			iEvent = ENone;
       
   332 			iSocket.Close();
       
   333 			iNotify->ResolverDisconnected();
       
   334 			}
       
   335 		else
       
   336 			{
       
   337 			}
       
   338 		break;
       
   339 		
       
   340 	default	:
       
   341 		// ERROR
       
   342 		break;
       
   343 		}
       
   344 	}