S60 3rd Edition SDK for Symbian OS
Example Applications Guide

ChatBt.cpp

00001 /*
00002 * ==============================================================================
00003 *  Name        : ChatBt.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 <coemain.h>
00019 #include <ChatEx.rsg>
00020 #include "ChatServiceAdvertiser.h"
00021 #include "ChatBt.h"
00022 #include "ChatServiceSearcher.h"
00023 #include "Chat.pan"
00024 #include "Log.h"
00025 
00026 // ============================ MEMBER FUNCTIONS ==============================
00027 
00028 // ----------------------------------------------------------------------------
00029 // CChatBt::NewL()
00030 // Two-phased constructor.
00031 // ----------------------------------------------------------------------------
00032 //
00033 CChatBt* CChatBt::NewL( MLog& aLog )
00034     {
00035     CChatBt* self = NewLC( aLog );
00036     CleanupStack::Pop( self );
00037     return self;
00038     }
00039 
00040 // ----------------------------------------------------------------------------
00041 // CChatBt::NewLC()
00042 // Two-phased constructor.
00043 // ----------------------------------------------------------------------------
00044 //
00045 CChatBt* CChatBt::NewLC( MLog& aLog )
00046     {
00047     CChatBt* self = new ( ELeave ) CChatBt( aLog );
00048     CleanupStack::PushL( self );
00049     self->ConstructL();
00050     return self;
00051     }
00052 
00053 // ----------------------------------------------------------------------------
00054 // CChatBt::CChatBt()
00055 // Constructor.
00056 // ----------------------------------------------------------------------------
00057 //
00058 CChatBt::CChatBt( MLog& aLog ) : 
00059     CChatBase( aLog ),
00060     iLog( aLog )
00061     {
00062     SetState( EWaitingToGetDevice );
00063     }
00064 
00065 // ----------------------------------------------------------------------------
00066 // CChatBt::~CChatBt()
00067 // Destructor.
00068 // ----------------------------------------------------------------------------
00069 //
00070 CChatBt::~CChatBt()
00071     {
00072     // Close() will wait forever for Read to complete
00073     if ( State() == EConnected )
00074         {
00075         if ( iActiveSocket )
00076             {
00077             iActiveSocket->CancelRead();
00078             }
00079         }
00080     Cancel();
00081 
00082     iSocket.Close();
00083     iAcceptedSocket.Close();
00084     iSocketServer.Close();
00085 
00086     delete iMessage;
00087     iMessage = NULL;
00088 
00089     delete iServiceSearcher;
00090     iServiceSearcher = NULL;
00091     
00092     delete iAdvertiser;
00093     iAdvertiser = NULL;
00094     }
00095 
00096 // ----------------------------------------------------------------------------
00097 // CChatBt::ConstructL()
00098 // Perform second phase construction of this object.
00099 // ----------------------------------------------------------------------------
00100 //
00101 void CChatBt::ConstructL()
00102     {
00103     iServiceSearcher = CChatServiceSearcher::NewL( iLog );
00104     iAdvertiser = CChatServiceAdvertiser::NewL();
00105     User::LeaveIfError( iSocketServer.Connect() );
00106     }
00107 
00108 // ----------------------------------------------------------------------------
00109 // CChatBt::DoCancel()
00110 // Cancel any outstanding requests.
00111 // ----------------------------------------------------------------------------
00112 //
00113 void CChatBt::DoCancel()
00114     {
00115     // no implementation required
00116     }
00117 
00118 // ----------------------------------------------------------------------------
00119 // CChatBt::RunL()
00120 // Respond to an event.
00121 // ----------------------------------------------------------------------------
00122 //
00123 void CChatBt::RunL()
00124     {
00125 
00126     HBufC* textResource = NULL;
00127     TBuf<KMaxMarkLen> mark;
00128   
00129     if ( iStatus == KErrDisconnected )
00130         {
00131         // Disconnected
00132         HBufC* strDisconnected = StringLoader
00133             ::LoadLC ( R_CHAT_STR_DISCONNECTED );
00134         iLog.LogL( *strDisconnected );
00135         CleanupStack::PopAndDestroy( strDisconnected );
00136         StopL();
00137         return;
00138         }
00139         
00140     else if ( iStatus == KErrAbort )
00141         {
00142         HBufC* strDisconnected = StringLoader
00143             ::LoadLC ( R_CHAT_STR_DISCONNECTED );
00144         iLog.LogL( *strDisconnected );
00145         CleanupStack::PopAndDestroy( strDisconnected );
00146         StopL();
00147         return;
00148         }
00149   
00150     else if ( iStatus != KErrNone )
00151         {
00152         switch ( State() )
00153             {
00154             case EGettingDevice:
00155                 if ( iStatus == KErrCancel )
00156                     {
00157                     textResource = StringLoader
00158                         ::LoadLC( R_CHAT_ERR_NO_DEVICE_SELECTED );
00159                     iLog.LogL( *textResource );
00160                     CleanupStack::PopAndDestroy( textResource );
00161                     }
00162                 SetState( EWaitingToGetDevice );
00163                 break;
00164                 
00165             case EGettingService:
00166             
00167             case EGettingConnection:
00168                 textResource = StringLoader
00169                     ::LoadLC( R_CHAT_ERR_CONNECTION_ERROR );
00170                 iLog.LogL( *textResource, iStatus.Int() );
00171                 CleanupStack::PopAndDestroy( textResource );
00172                 SetState( EWaitingToGetDevice );
00173                 break;
00174                 
00175             case EConnected:
00176                 textResource = StringLoader
00177                     ::LoadLC( R_CHAT_ERR_LOST_CONNECTION );
00178                 iLog.LogL( *textResource, iStatus.Int() );
00179                 DisconnectFromServerL();
00180                 CleanupStack::PopAndDestroy( textResource );
00181                 SetState( EDisconnecting );
00182                 break;
00183                 
00184             case ESendingMessage:
00185                 textResource = StringLoader
00186                     ::LoadLC( R_CHAT_ERR_MESSAGE_FAILED );
00187                 iLog.LogL( *textResource, iStatus.Int() );
00188                 CleanupStack::PopAndDestroy( textResource );
00189                 DisconnectFromServerL();
00190                 SetState( EDisconnecting );
00191                 break;
00192                 
00193             case EDisconnecting:
00194                 if ( iStatus == KErrDisconnected )
00195                     {
00196                     textResource = StringLoader
00197                         ::LoadLC( R_CHAT_DISCONNECT_COMPLETE );
00198                     iLog.LogL( *textResource, iStatus.Int() );
00199                     CleanupStack::PopAndDestroy( textResource );
00200 
00201                     StopL();
00202                     SetState( EWaitingToGetDevice );
00203                     }
00204                 else
00205                     {
00206                     textResource = StringLoader
00207                         ::LoadLC( R_CHAT_ERR_FAILED_TO_DISCONNECT );
00208                     iLog.LogL( *textResource, iStatus.Int() );
00209                     CleanupStack::PopAndDestroy( textResource );
00210 
00211                     Panic( EChatUnableToDisconnect );
00212                     }
00213                 break;
00214             
00215             case EWaitingToGetDevice:
00216                 textResource = StringLoader
00217                     ::LoadLC( R_CHAT_STR_DISCONNECTED );
00218                 iLog.LogL( *textResource );
00219                 CleanupStack::PopAndDestroy( textResource );
00220                 break;
00221                 
00222             default:
00223                 Panic( EChatInvalidLogicState );
00224                 break;
00225             }
00226         }
00227         
00228     else 
00229         {
00230         switch ( State() )
00231             {
00232             case EGettingDevice:
00233                 // found a device now search for a suitable service
00234                 iLog.LogL( iServiceSearcher->ResponseParams().DeviceName() );
00235                 SetState( EGettingService );
00236                 iStatus = KRequestPending;  // this means that the RunL 
00237                                             // can not be called until
00238                                             // this program does something 
00239                                             // to iStatus
00240                 iServiceSearcher->FindServiceL( iStatus );
00241                 SetActive();
00242                 break;
00243                 
00244             case EConnecting:
00245                 textResource = StringLoader::LoadLC ( R_CHAT_CONNECTED );
00246                 iLog.LogL( *textResource );
00247                 CleanupStack::PopAndDestroy( textResource );
00248               
00249                 // do not accept any more connections
00250                 iAdvertiser->UpdateAvailabilityL( EFalse );
00251                 RequestData();
00252                 SetState( EConnected );
00253                 break;
00254                 
00255             case EGettingService:
00256                 textResource = StringLoader
00257                     ::LoadLC( R_CHAT_FOUND_SERVICE );
00258                 iLog.LogL( *textResource );
00259                 CleanupStack::PopAndDestroy( textResource );
00260                 SetState( EGettingConnection );
00261                 ConnectToServerL();
00262                 break;
00263                 
00264             case EGettingConnection:
00265                 textResource = StringLoader
00266                     ::LoadLC( R_CHAT_CONNECTED );
00267                 iLog.LogL( *textResource );
00268                 CleanupStack::PopAndDestroy( textResource );
00269                 SetState( EConnected );
00270                 RequestData();
00271                 break;
00272                 
00273             case EConnected:
00274               
00275                 mark.Append( '>' );
00276                 textResource = HBufC::NewLC( iBuffer.Length() );
00277                 textResource->Des().Copy( iBuffer );
00278                 iLog.LogL( *textResource, mark );
00279                 iBuffer.Zero();
00280                 CleanupStack::PopAndDestroy( textResource );
00281                 RequestData();
00282                 break;
00283                 
00284             case ESendingMessage:
00285                 SetState( EConnected );
00286                 RequestData();
00287                 break;
00288                 
00289             case EDisconnecting:
00290                 textResource = StringLoader
00291                     ::LoadLC( R_CHAT_DISCONNECT_COMPLETE );
00292                 iLog.LogL( *textResource );
00293                 CleanupStack::PopAndDestroy ( textResource );
00294                 iSocket.Close();
00295                 SetState( EWaitingToGetDevice );
00296                 break;
00297             
00298             case EWaitingToGetDevice:
00299                 
00300                 break;
00301                 
00302             default:
00303                 Panic( EChatInvalidLogicState );
00304                 break;
00305             };
00306         }
00307     }
00308 
00309 // ----------------------------------------------------------------------------
00310 // CChatBt::ConnectL()
00311 // Connect to a service.
00312 // ----------------------------------------------------------------------------
00313 //
00314 void CChatBt::ConnectL()
00315     {
00316     if ( State() == EWaitingToGetDevice && !IsActive() )
00317         {
00318         SetState( EGettingDevice );
00319         iServiceSearcher->SelectDeviceByDiscoveryL( iStatus );
00320         SetActive();
00321         }
00322     else
00323         {
00324         HBufC* errClientBusy = StringLoader::LoadLC ( R_CHAT_CLIENT_BUSY );
00325         iLog.LogL( *errClientBusy );
00326         CleanupStack::PopAndDestroy( errClientBusy );
00327 
00328         User::Leave( KErrInUse );
00329         }
00330     }
00331 
00332 // ----------------------------------------------------------------------------
00333 // CChatBt::DisconnectL()
00334 // Disconnects from the remote machine.
00335 // ----------------------------------------------------------------------------
00336 //
00337 void CChatBt::DisconnectL()
00338     {
00339     if ( ( State() == EConnected )||( State() == ESendingMessage ) )
00340         {
00341         DisconnectFromServerL();
00342         SetState( EDisconnecting );
00343         }
00344     else
00345         {
00346         HBufC* errNoConn = StringLoader::LoadLC ( R_CHAT_ERR_NO_CONN );
00347         iLog.LogL( *errNoConn );
00348         CleanupStack::PopAndDestroy( errNoConn );
00349         User::Leave( KErrDisconnected );
00350         }
00351     }
00352 
00353 // ----------------------------------------------------------------------------
00354 // CChatBt::DisconnectFromServerL()
00355 // Disconnects from the service
00356 // ----------------------------------------------------------------------------
00357 //
00358 void CChatBt::DisconnectFromServerL()
00359     {
00360     // Terminate all operations
00361     iSocket.CancelAll();
00362     Cancel();
00363 
00364     HBufC* strReleasingConn = StringLoader
00365         ::LoadLC ( R_CHAT_STR_RELEASING_CONN );
00366     iLog.LogL( *strReleasingConn );
00367     CleanupStack::PopAndDestroy( strReleasingConn );
00368     iSocket.Shutdown( RSocket::ENormal, iStatus );
00369     SetActive();
00370     }
00371 
00372 // ----------------------------------------------------------------------------
00373 // CChatBt::ConnectToServerL()
00374 // Connect to the server.
00375 // ----------------------------------------------------------------------------
00376 //
00377 void CChatBt::ConnectToServerL()
00378     {
00379     HBufC* strConnecting = StringLoader
00380         ::LoadLC ( R_CHAT_STR_CONNECTING );
00381     iLog.LogL( *strConnecting );
00382     CleanupStack::PopAndDestroy( strConnecting );
00383 
00384     User::LeaveIfError( iSocket.Open( iSocketServer, KStrRFCOMM ) );
00385 
00386     TBTSockAddr address;
00387     address.SetBTAddr( iServiceSearcher->BTDevAddr() );
00388     address.SetPort( iServiceSearcher->Port() );
00389 
00390     iSocket.Connect( address, iStatus );
00391   
00392     iActiveSocket = &iSocket;
00393   
00394     #ifdef __WINS__
00395         // Fix to allow emulator client to connect to server
00396         User::After( 1 );     
00397     #endif
00398   
00399     SetActive();
00400     }
00401 
00402 
00403 // ----------------------------------------------------------------------------
00404 // CChatBt::SendMessageL()
00405 // Send a message to a service on a remote machine.
00406 // ----------------------------------------------------------------------------
00407 //
00408 void CChatBt::SendMessageL( TDes& aText )
00409     {
00410 
00411     if ( State() != EConnected )
00412         {
00413         User::Leave( KErrDisconnected );
00414         }
00415 
00416     // stop reading socket
00417     if ( iActiveSocket )
00418         {
00419         iActiveSocket->CancelRead();
00420         }
00421 
00422     if ( IsActive() )
00423         {
00424         Cancel();
00425         }
00426     TBufC<KChatTextBufLength> message ( aText );
00427     SetState( ESendingMessage );
00428     HBufC* tempString = HBufC::NewL( message.Length() );
00429     CleanupStack::PushL( tempString );
00430     tempString->Des().Copy( message );
00431     
00432     iMessage = HBufC8::NewL(tempString->Length());
00433     CleanupStack::Pop( tempString );
00434     iMessage->Des().Copy( *tempString );
00435     
00436     if ( iActiveSocket )
00437         {
00438         iActiveSocket->Write( *iMessage, iStatus );
00439         }
00440 
00441     delete tempString;
00442     
00443     SetActive();
00444     }
00445 
00446 
00447 
00448 // ----------------------------------------------------------------------------
00449 // CChatBt::StartL()
00450 // Starts the server.
00451 // ----------------------------------------------------------------------------
00452 //
00453 void CChatBt::StartL()
00454     {
00455     if ( State() != EWaitingToGetDevice )
00456         {
00457         User::Leave( KErrInUse );
00458         }
00459 
00460     TInt result( 0 );
00461     result = iSocket.Open( iSocketServer, KStrRFCOMM );
00462     if ( result != KErrNone )
00463         {
00464         iSocketServer.Close();
00465         User::Leave( result ); 
00466         }
00467 
00468    
00469     // 
00470     // Set the Socket's security with parameters, 
00471     // Authentication, Encryption, Authorisation and Denied
00472     // Method also return the channel available to listen to. 
00473     TInt channel;
00474     SetSecurityWithChannelL( EFalse, EFalse, ETrue, EFalse, channel );
00475 
00476     iAdvertiser->StartAdvertisingL( channel );
00477     iAdvertiser->UpdateAvailabilityL( ETrue );
00478     
00479     SetServer( ETrue );
00480 
00481     }
00482 
00483 // ----------------------------------------------------------------------------
00484 // CChatBt::SetSecurityWithChannelL( )
00485 // Sets the security on the channel port and returns the available port.
00486 // ----------------------------------------------------------------------------
00487 //
00488 void CChatBt::SetSecurityWithChannelL( 
00489     TBool aAuthentication,
00490     TBool aEncryption,
00491     TBool aAuthorisation,
00492     TBool aDenied,
00493     TInt& aChannel )
00494 
00495     {
00496 
00497     // Local variable to channel to listen to.
00498     TInt channel;
00499 
00500 
00501     User::LeaveIfError( iSocket.GetOpt( 
00502         KRFCOMMGetAvailableServerChannel, 
00503         KSolBtRFCOMM, 
00504         channel ) );
00505 
00506     TBTSockAddr listeningAddress;
00507     // Set the Port to listen to.
00508     listeningAddress.SetPort( channel );
00509 
00510     // Write Log events
00511     HBufC* strGetPort = StringLoader::LoadLC ( R_CHAT_STR_GET_PORT );
00512 
00513     iLog.LogL( *strGetPort, channel );
00514     CleanupStack::PopAndDestroy( strGetPort );
00515 
00516 
00517     User::LeaveIfError( iSocket.Bind( listeningAddress ) );
00518     User::LeaveIfError( iSocket.Listen( KListeningQueSize ) );
00519 
00520      // close old connection - if any
00521     iAcceptedSocket.Close();
00522 
00523     // Open abstract socket
00524     User::LeaveIfError( iAcceptedSocket.Open( iSocketServer ) );  
00525 
00526     // Set the Active Object's State to Connecting indicated.
00527     SetState( EConnecting );
00528 
00529     iSocket.Accept( iAcceptedSocket, iStatus );
00530   
00531     iActiveSocket = &iAcceptedSocket;
00532   
00533     // Set the Active Object Active again,
00534     SetActive();
00535 
00536     // Write Log events
00537     HBufC* acceptNextConn = StringLoader::LoadLC ( 
00538         R_CHAT_ACCEPT_NEXT_CONN );
00539     iLog.LogL( *acceptNextConn );
00540     CleanupStack::PopAndDestroy( acceptNextConn );
00541 
00542  
00543     // Set the security according to.
00544     TBTServiceSecurity serviceSecurity;
00545     serviceSecurity.SetUid ( KUidChatApp );
00546     serviceSecurity.SetAuthentication ( aAuthentication );
00547     serviceSecurity.SetEncryption ( aEncryption );
00548     serviceSecurity.SetAuthorisation ( aAuthorisation );
00549     serviceSecurity.SetDenied( aDenied );
00550 
00551     // Attach the security settings.
00552     listeningAddress.SetSecurity(serviceSecurity);
00553 
00554     // Return the port to listen to.
00555     aChannel = channel;
00556   
00557     }
00558                       
00559 
00560 // ----------------------------------------------------------------------------
00561 // CChatBt::StopL()
00562 // Stops the server.
00563 // ----------------------------------------------------------------------------
00564 //
00565 void CChatBt::StopL()
00566     {
00567     if ( State() != EDisconnected )
00568         {
00569         if ( iAdvertiser->IsAdvertising() )
00570             {
00571             iAdvertiser->StopAdvertisingL();
00572             }
00573         // Close() will wait forever for Read to complete
00574         if ( State() == EConnected )
00575             {
00576             if ( iActiveSocket )
00577                 {
00578                 iActiveSocket->CancelRead();
00579                 }
00580             }    
00581         iAcceptedSocket.Close();
00582         iSocket.Close();
00583         }
00584         SetState( EWaitingToGetDevice );
00585     }
00586 
00587 // ----------------------------------------------------------------------------
00588 // CChatBt::RequestData()
00589 // Request data from the client.
00590 // ----------------------------------------------------------------------------
00591 //
00592 void CChatBt::RequestData()
00593     {
00594     if ( iActiveSocket )
00595         {
00596         iActiveSocket->RecvOneOrMore( iBuffer, 0, iStatus, iLen );
00597         }
00598     SetActive();
00599     }
00600 
00601 // End of File

© Nokia 2006

Back to top