S60 3rd Edition SDK for Symbian OS
Example Applications Guide

ChatInet.cpp

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

Back to top