|
S60 3rd Edition SDK for Symbian OS Example Applications Guide |
00001 /* 00002 * ============================================================================== 00003 * Name : ChatInet.cpp 00004 * Part of : Chat 00005 * Interface : 00006 * Description : 00007 * Version : 00008 * 00009 * Copyright (c) 2005-2006 Nokia Corporation. 00010 * This material, including documentation and any related 00011 * computer programs, is protected by copyright controlled by 00012 * Nokia Corporation. 00013 * ============================================================================== 00014 */ 00015 00016 // INCLUDE FILES 00017 #include <StringLoader.h> 00018 #include <ChatEx.rsg> 00019 #include <coemain.h> 00020 00021 #include "ChatInet.h" 00022 #include "Chat.pan" 00023 #include "Log.h" 00024 #include "es_enum.h" 00025 00026 // ============================ MEMBER FUNCTIONS ============================== 00027 00028 // ---------------------------------------------------------------------------- 00029 // CChatInet::NewL() 00030 // Two-phased constructor. 00031 // ---------------------------------------------------------------------------- 00032 // 00033 CChatInet* CChatInet::NewL( MLog& aLog ) 00034 { 00035 CChatInet* self = NewLC( aLog ); 00036 CleanupStack::Pop( self ); 00037 return self; 00038 } 00039 00040 // ---------------------------------------------------------------------------- 00041 // CChatInet::NewLC() 00042 // Two-phased constructor. 00043 // ---------------------------------------------------------------------------- 00044 // 00045 CChatInet* CChatInet::NewLC( MLog& aLog ) 00046 { 00047 CChatInet* self = new ( ELeave ) CChatInet( aLog ); 00048 CleanupStack::PushL( self ); 00049 self->ConstructL (); 00050 return self; 00051 00052 } 00053 00054 // ---------------------------------------------------------------------------- 00055 // CChatInet::CChatInet() 00056 // Constructor. 00057 // ---------------------------------------------------------------------------- 00058 // 00059 CChatInet::CChatInet( MLog& aLog ) : 00060 CChatBase( aLog ), 00061 iLog( aLog ), 00062 iPort( KDefaultPortNumber ) 00063 { 00064 SetState( EDisconnected ); 00065 } 00066 00067 // ---------------------------------------------------------------------------- 00068 // CChatInet::~CChatInet() 00069 // Destructor. 00070 // ---------------------------------------------------------------------------- 00071 // 00072 CChatInet::~CChatInet() 00073 { 00074 // Close() will wait forever for Read to complete 00075 if ( State() == EConnected ) 00076 { 00077 if ( iActiveSocket ) 00078 { 00079 iActiveSocket->CancelRead(); 00080 } 00081 } 00082 Cancel(); 00083 iAcceptedSocket.Close(); 00084 iSocket.Close(); 00085 iSocketServer.Close(); 00086 00087 delete iMessage; 00088 iMessage = NULL; 00089 } 00090 00091 // ---------------------------------------------------------------------------- 00092 // CChatInet::ConstructL() 00093 // Perform second phase construction of this object. 00094 // ---------------------------------------------------------------------------- 00095 // 00096 void CChatInet::ConstructL() 00097 { 00098 User::LeaveIfError( iSocketServer.Connect() ); 00099 } 00100 00101 // ---------------------------------------------------------------------------- 00102 // CChatInet::DoCancel() 00103 // Cancel any outstanding requests. 00104 // ---------------------------------------------------------------------------- 00105 // 00106 void CChatInet::DoCancel() 00107 { 00108 if ( State() == EConnected ) 00109 { 00110 if ( iActiveSocket ) 00111 { 00112 iActiveSocket->CancelRead(); 00113 } 00114 } 00115 SetState( EDisconnected ); 00116 } 00117 00118 // ---------------------------------------------------------------------------- 00119 // CChatInet::RunL() 00120 // Respond to an event. 00121 // ---------------------------------------------------------------------------- 00122 // 00123 void CChatInet::RunL() 00124 { 00125 HBufC* textResource = NULL; 00126 TBuf<KMaxMarkLen> mark; 00127 00128 if ( ( iStatus == KErrDisconnected ) || ( iStatus == KErrEof ) ) 00129 { 00130 // Disconnected so go back to listening 00131 HBufC* strDisconnected = StringLoader 00132 ::LoadLC ( R_CHAT_STR_DISCONNECTED ); 00133 iLog.LogL( *strDisconnected ); 00134 CleanupStack::PopAndDestroy( strDisconnected ); 00135 Stop(); 00136 return; 00137 } 00138 else if ( iStatus == KErrAbort ) 00139 { 00140 HBufC* strDisconnected = StringLoader 00141 ::LoadLC ( R_CHAT_STR_DISCONNECTED ); 00142 iLog.LogL( *strDisconnected ); 00143 CleanupStack::PopAndDestroy( strDisconnected ); 00144 Stop(); 00145 return; 00146 } 00147 00148 else if ( iStatus != KErrNone ) 00149 { 00150 switch ( State() ) 00151 { 00152 case EGettingConnection: 00153 textResource = StringLoader 00154 ::LoadLC( R_CHAT_ERR_CONNECTION_ERROR ); 00155 iLog.LogL( *textResource, iStatus.Int() ); 00156 DisconnectFromServerL(); 00157 CleanupStack::PopAndDestroy( textResource ); 00158 SetState( EDisconnecting ); 00159 break; 00160 00161 case EConnected: 00162 textResource = StringLoader 00163 ::LoadLC( R_CHAT_ERR_LOST_CONNECTION ); 00164 iLog.LogL( *textResource, iStatus.Int() ); 00165 DisconnectFromServerL(); 00166 CleanupStack::PopAndDestroy( textResource ); 00167 SetState( EDisconnecting ); 00168 break; 00169 00170 case ESendingMessage: 00171 textResource = StringLoader 00172 ::LoadLC( R_CHAT_ERR_MESSAGE_FAILED ); 00173 iLog.LogL( *textResource, iStatus.Int() ); 00174 CleanupStack::PopAndDestroy( textResource ); 00175 DisconnectFromServerL(); 00176 SetState( EDisconnecting ); 00177 break; 00178 00179 case EDisconnecting: 00180 if ( iStatus == KErrDisconnected ) 00181 { 00182 textResource = StringLoader 00183 ::LoadLC( R_CHAT_DISCONNECT_COMPLETE ); 00184 iLog.LogL( *textResource, iStatus.Int() ); 00185 CleanupStack::PopAndDestroy( textResource ); 00186 Stop(); 00187 SetState( EDisconnected ); 00188 } 00189 else 00190 { 00191 textResource = StringLoader 00192 ::LoadLC( R_CHAT_ERR_FAILED_TO_DISCONNECT ); 00193 iLog.LogL( *textResource, iStatus.Int() ); 00194 CleanupStack::PopAndDestroy( textResource ); 00195 } 00196 break; 00197 00198 case EDisconnected: 00199 textResource = StringLoader 00200 ::LoadLC( R_CHAT_DISCONNECT_COMPLETE ); 00201 iLog.LogL( *textResource, iStatus.Int() ); 00202 CleanupStack::PopAndDestroy( textResource ); 00203 break; 00204 00205 default: 00206 break; 00207 } 00208 } 00209 else 00210 { 00211 switch ( State() ) 00212 { 00213 00214 case EGettingConnection: 00215 textResource = StringLoader 00216 ::LoadLC( R_CHAT_CONNECTED ); 00217 iLog.LogL( *textResource ); 00218 CleanupStack::PopAndDestroy( textResource ); 00219 00220 SetState( EConnected ); 00221 RequestData(); 00222 break; 00223 00224 case EConnected: 00225 00226 mark.Append( '>' ); 00227 textResource = HBufC::NewLC( iBuffer.Length() ); 00228 textResource->Des().Copy( iBuffer ); 00229 iLog.LogL( *textResource, mark ); 00230 iBuffer.Zero(); 00231 CleanupStack::PopAndDestroy( textResource ); 00232 RequestData(); 00233 break; 00234 00235 case ESendingMessage: 00236 SetState( EConnected ); 00237 RequestData(); 00238 break; 00239 00240 case EDisconnecting: 00241 textResource = StringLoader 00242 ::LoadLC( R_CHAT_DISCONNECT_COMPLETE ); 00243 iLog.LogL( *textResource ); 00244 CleanupStack::PopAndDestroy ( textResource ); 00245 00246 Stop(); 00247 SetState( EDisconnected ); 00248 break; 00249 00250 case EDisconnected: 00251 break; 00252 00253 default: 00254 Panic( EChatInvalidLogicState ); 00255 break; 00256 }; 00257 } 00258 } 00259 00260 // ---------------------------------------------------------------------------- 00261 // CChatInet::ConnectL() 00262 // Connect to a service. 00263 // ---------------------------------------------------------------------------- 00264 // 00265 void CChatInet::ConnectL( const TDesC& aAddress ) 00266 { 00267 if ( State() == EDisconnected && !IsActive() ) 00268 { 00269 SetState( EGettingConnection ); 00270 ConnectToServerL( aAddress ); 00271 } 00272 else 00273 { 00274 HBufC* errClientBusy = StringLoader::LoadLC ( R_CHAT_CLIENT_BUSY ); 00275 iLog.LogL( *errClientBusy ); 00276 CleanupStack::PopAndDestroy( errClientBusy ); 00277 00278 User::Leave( KErrInUse ); 00279 } 00280 } 00281 00282 // ---------------------------------------------------------------------------- 00283 // CChatInet::DisconnectL() 00284 // Disconnects from the remote machine. 00285 // ---------------------------------------------------------------------------- 00286 // 00287 void CChatInet::DisconnectL() 00288 { 00289 if ( ( State() == EConnected )||( State() == ESendingMessage ) ) 00290 { 00291 DisconnectFromServerL(); 00292 SetState( EDisconnecting ); 00293 } 00294 else 00295 { 00296 HBufC* errNoConn = StringLoader::LoadLC ( R_CHAT_ERR_NO_CONN ); 00297 iLog.LogL( *errNoConn ); 00298 CleanupStack::PopAndDestroy( errNoConn ); 00299 User::Leave( KErrDisconnected ); 00300 } 00301 } 00302 00303 // ---------------------------------------------------------------------------- 00304 // CChatInet::DisconnectFromServerL() 00305 // Disconnects from the service 00306 // ---------------------------------------------------------------------------- 00307 // 00308 void CChatInet::DisconnectFromServerL() 00309 { 00310 // Terminate all operations 00311 iSocket.CancelAll(); 00312 Cancel(); 00313 00314 HBufC* strReleasingConn = StringLoader 00315 ::LoadLC ( R_CHAT_STR_RELEASING_CONN ); 00316 iLog.LogL( *strReleasingConn ); 00317 CleanupStack::PopAndDestroy( strReleasingConn ); 00318 iSocket.Shutdown( RSocket::ENormal, iStatus ); 00319 SetActive(); 00320 } 00321 00322 // ---------------------------------------------------------------------------- 00323 // CChatInet::ConnectToServerL() 00324 // Connect to the server. 00325 // ---------------------------------------------------------------------------- 00326 // 00327 void CChatInet::ConnectToServerL( const TDesC& aAddress ) 00328 { 00329 HBufC* strConnecting = StringLoader 00330 ::LoadLC ( R_CHAT_STR_CONNECTING ); 00331 iLog.LogL( *strConnecting ); 00332 CleanupStack::PopAndDestroy( strConnecting ); 00333 00334 TInetAddr addr; 00335 if ( addr.Input( aAddress ) == KErrNone ) 00336 { 00337 // server name is already a valid ip address 00338 ConnectL( addr.Address() ); 00339 } 00340 else 00341 { 00342 // Initiate DNS 00343 User::LeaveIfError( iResolver.Open( iSocketServer, 00344 KAfInet, 00345 KProtocolInetTcp ) ); 00346 // DNS request for name resolution 00347 iResolver.GetByName( aAddress, iNameEntry, iStatus ); 00348 00349 TRequestStatus waitStatus = KRequestPending; 00350 RTimer timer; 00351 timer.CreateLocal(); 00352 00353 timer.After( waitStatus, KChatTimeOut ); 00354 00355 User::WaitForRequest( iStatus, waitStatus ); 00356 00357 if ( iStatus == KRequestPending ) 00358 { 00359 iResolver.Cancel(); 00360 00361 User::WaitForRequest( iStatus ); 00362 iResolver.Close(); 00363 // Operation did not complete in time. 00364 HBufC* strConnecting = StringLoader 00365 ::LoadLC ( R_CHAT_ERR_TIMEOUT ); 00366 iLog.LogL( *strConnecting ); 00367 CleanupStack::PopAndDestroy( strConnecting ); 00368 SetState( EDisconnected ); 00369 timer.Close(); 00370 User::Leave( KErrTimedOut ); 00371 00372 } 00373 else 00374 { 00375 // DNS look up successful 00376 iNameRecord = iNameEntry(); 00377 TBuf<KIpAddressLen> ipAddr; 00378 TInetAddr::Cast( iNameRecord.iAddr ).Output( ipAddr ); 00379 ConnectL( TInetAddr::Cast( iNameRecord.iAddr ).Address() ); 00380 00381 timer.Cancel(); 00382 User::WaitForRequest( waitStatus ); 00383 timer.Close(); 00384 iResolver.Close(); 00385 } 00386 00387 } 00388 00389 #ifdef __WINS__ 00390 User::After( 1 ); // Fix to allow emulator client to connect to server 00391 #endif 00392 00393 SetState( EGettingConnection ); 00394 00395 SetActive(); 00396 } 00397 00398 00399 // ----------------------------------------------------------------------------- 00400 // CChatInet::ConnectL() 00401 // Initiates a connect operation on a socket. 00402 // ----------------------------------------------------------------------------- 00403 // 00404 void CChatInet::ConnectL( TUint32 aAddr ) 00405 { 00406 iActiveSocket = &iSocket; 00407 iAddress.SetPort( iPort ); 00408 iAddress.SetAddress( aAddr ); 00409 iAddress.SetFamily( KAfInet ); 00410 00411 // Open a TCP socket 00412 User::LeaveIfError( iSocket.Open( iSocketServer, 00413 KAfInet, 00414 KSockStream, 00415 KProtocolInetTcp ) ); 00416 00417 // Initiate socket connection 00418 iSocket.Connect( iAddress, iStatus ); 00419 } 00420 00421 00422 // ---------------------------------------------------------------------------- 00423 // CChatInet::SendMessageL() 00424 // Send a message to a service on a remote machine. 00425 // ---------------------------------------------------------------------------- 00426 // 00427 void CChatInet::SendMessageL( const TDesC& aText ) 00428 { 00429 if ( State() != EConnected ) 00430 { 00431 User::Leave( KErrDisconnected ); 00432 } 00433 00434 // stop reading socket 00435 if ( iActiveSocket ) 00436 { 00437 iActiveSocket->CancelRead(); 00438 } 00439 00440 if ( IsActive() ) 00441 { 00442 Cancel(); 00443 } 00444 00445 TBufC<KChatTextBufLength> message ( aText ); 00446 SetState( ESendingMessage ); 00447 HBufC* tempString = HBufC::NewL( message.Length() ); 00448 tempString->Des().Copy( message ); 00449 00450 iMessage = HBufC8::NewL(tempString->Length()); 00451 iMessage->Des().Copy( *tempString ); 00452 00453 // write message to socket 00454 if ( iActiveSocket ) 00455 { 00456 iActiveSocket->Write( *iMessage, iStatus ); 00457 } 00458 delete tempString; 00459 SetActive(); 00460 } 00461 00462 00463 // ---------------------------------------------------------------------------- 00464 // CChatInet::StartL() 00465 // Starts the server. 00466 // ---------------------------------------------------------------------------- 00467 // 00468 void CChatInet::StartL() 00469 { 00470 if ( State() != EDisconnected ) 00471 { 00472 User::Leave( KErrInUse ); 00473 } 00474 00475 User::LeaveIfError( iConnection.Open( iSocketServer, KAfInet) ); 00476 00477 User::LeaveIfError( iConnection.Start() ); 00478 00479 TInt result( 0 ); 00480 00481 result = iSocket.Open( iSocketServer, 00482 KAfInet, 00483 KSockStream, 00484 KProtocolInetTcp ); 00485 00486 if ( result != KErrNone ) 00487 { 00488 iSocketServer.Close(); 00489 User::Leave( result ); 00490 } 00491 00492 TInetAddr addr; 00493 iAddress.SetPort( iPort ); 00494 iAddress.SetFamily( KAfInet ); 00495 00496 // bind 00497 User::LeaveIfError( iSocket.Bind( iAddress ) ); 00498 00499 // listen 00500 User::LeaveIfError( iSocket.Listen( KListeningQueSize ) ); 00501 00502 // close old connection - if any 00503 iAcceptedSocket.Close(); 00504 00505 // Open abstract socket 00506 User::LeaveIfError( iAcceptedSocket.Open( iSocketServer ) ); 00507 00508 iActiveSocket = &iAcceptedSocket; 00509 00510 // Set the Active Object's State to Connecting indicated. 00511 SetState( EGettingConnection ); 00512 00513 iSocket.Accept( iAcceptedSocket, iStatus ); 00514 00515 SetServer( ETrue ); 00516 00517 // Set the Active Object Active again, 00518 SetActive(); 00519 00520 } 00521 00522 00523 // ---------------------------------------------------------------------------- 00524 // CChatInet::Stop() 00525 // Stops the server. 00526 // ---------------------------------------------------------------------------- 00527 // 00528 void CChatInet::Stop() 00529 { 00530 if ( State() != EDisconnected ) 00531 { 00532 // Close() will wait forever for Read to complete 00533 if ( State() == EConnected ) 00534 { 00535 if ( iActiveSocket ) 00536 { 00537 iActiveSocket->CancelRead(); 00538 } 00539 } 00540 iAcceptedSocket.Close(); 00541 iSocket.Close(); 00542 } 00543 SetState( EDisconnected ); 00544 } 00545 00546 // ---------------------------------------------------------------------------- 00547 // CChatInet::RequestData() 00548 // Request data from the client. 00549 // ---------------------------------------------------------------------------- 00550 // 00551 void CChatInet::RequestData() 00552 { 00553 if ( iActiveSocket ) 00554 { 00555 iActiveSocket->RecvOneOrMore( iBuffer, 0, iStatus, iLen ); 00556 } 00557 SetActive(); 00558 } 00559 00560 00561 // End of File
|
© Nokia 2006 |