S60 3rd Edition SDK for Symbian OS
Example Applications Guide

SIPExSocketEngine.cpp

00001 /*
00002 * ==============================================================================
00003 *  Name        : SIPExSocketEngine.cpp
00004 *  Part of     : SIPExSocketEngine
00005 *  Interface   : 
00006 *  Description : 
00007 *  Version     : 
00008 *
00009 *  Copyright (c) 2004-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 // INCLUDES
00017 #include    "SIPExSocketEngine.h"
00018 #include    "SIPExSocketWriter.h"
00019 #include    "SIPExSocketReader.h"
00020 #include    "SIPExTimeOutTimer.h"
00021 #include    <e32svr.h>
00022 #include    <CommDbConnPref.h>
00023 
00024 // CONSTANTS
00025 const TInt KGamePort( 10011 );
00026 
00027 // -----------------------------------------------------------------------------
00028 // CSIPExSocketEngine::NewL
00029 // Creates the instance of class and returns it.
00030 // -----------------------------------------------------------------------------
00031 //
00032 EXPORT_C CSIPExSocketEngine* CSIPExSocketEngine::NewL( 
00033     MSIPExSocketEngineObserver& aObserver )
00034     {
00035     CSIPExSocketEngine* self = CSIPExSocketEngine::NewLC( aObserver );
00036     CleanupStack::Pop(self);
00037     return self;
00038     }
00039 
00040 // -----------------------------------------------------------------------------
00041 // CSIPExSocketEngine::NewLC
00042 // Creates the instance of class and pushes it to the CleanupStack and return
00043 // it.
00044 // -----------------------------------------------------------------------------
00045 //    
00046 EXPORT_C CSIPExSocketEngine* CSIPExSocketEngine::NewLC( 
00047     MSIPExSocketEngineObserver& aObserver )
00048     {
00049     CSIPExSocketEngine* self = new (ELeave) CSIPExSocketEngine( aObserver );
00050     CleanupStack::PushL(self);
00051     self->ConstructL();
00052     return self;
00053     }
00054 
00055 // -----------------------------------------------------------------------------
00056 // CSIPExSocketEngine::CSIPExSocketEngine
00057 // Calls base classes constructor with priority value. Add class to the 
00058 // active sheduler.
00059 // -----------------------------------------------------------------------------
00060 //
00061 CSIPExSocketEngine::CSIPExSocketEngine( MSIPExSocketEngineObserver& aObserver )
00062 :   CActive( EPriorityStandard ), iObserver( aObserver )
00063     {
00064     CActiveScheduler::Add( this );
00065     }
00066 
00067 // -----------------------------------------------------------------------------
00068 // CSIPExSocketEngine::~CSIPExSocketEngine
00069 // Cancels any outstanding requests and deletes members.
00070 // -----------------------------------------------------------------------------
00071 //
00072 EXPORT_C CSIPExSocketEngine::~CSIPExSocketEngine()
00073     {
00074     Cancel();
00075     
00076         if ( iTimer )
00077                 {
00078                 iTimer->Cancel();
00079                 delete iTimer;
00080                 }
00081 
00082         if ( iWriter )
00083                 {
00084                 iWriter->Cancel();
00085                 delete iWriter;
00086                 }
00087 
00088         if ( iReader )
00089                 {
00090                 iReader->Cancel();
00091                 delete iReader;
00092                 }
00093 
00094     iListenSocket.Close();
00095     iDataSocket.Close();
00096     iConnection.Close();
00097     iSocketServer.Close();
00098     }
00099 
00100 // -----------------------------------------------------------------------------
00101 // CSIPExSocketEngine::ConstructL
00102 // The socketserver is connected and members created.
00103 // -----------------------------------------------------------------------------
00104 //
00105 void CSIPExSocketEngine::ConstructL()
00106     {
00107     iState = ENotConnected;
00108 
00109     iTimer = CSIPExTimeOutTimer::NewL( *this );
00110 
00111     // Open channel to Socket Server
00112         User::LeaveIfError( iSocketServer.Connect() );
00113 
00114     iReader = CSIPExSocketReader::NewL( iDataSocket, *this );
00115     iWriter = CSIPExSocketWriter::NewL( iDataSocket, *this );
00116     }
00117 
00118 // -----------------------------------------------------------------------------
00119 // CSIPExSocketEngine::DoCancel
00120 // From CActive. Cancels any outstanding request according the engine state.
00121 // -----------------------------------------------------------------------------
00122 //
00123 void CSIPExSocketEngine::DoCancel()
00124     {    
00125     iTimer->Cancel();
00126 
00127     // Cancel appropriate request to socket
00128         switch ( iState )
00129                 {
00130             case EConnecting:
00131                     iDataSocket.CancelConnect();
00132                     break;
00133 
00134         case EListening:
00135             iListenSocket.CancelAccept();
00136             break;
00137         
00138         default:
00139             break;
00140         }    
00141         
00142     iConnection.Close();
00143     }
00144 
00145 // -----------------------------------------------------------------------------
00146 // CSIPExSocketEngine::RunL
00147 // From CActive. Handles the state changes and notifing the observer.
00148 // -----------------------------------------------------------------------------
00149 //
00150 void CSIPExSocketEngine::RunL()
00151     {
00152     iTimer->Cancel();
00153 
00154     switch( iState )
00155         {
00156         case EConnecting:
00157             if( iStatus.Int() == KErrNone )
00158                 {
00159                 ChangeStateAndNotify( EConnected );
00160                 Read();
00161                 }
00162             else
00163                 {
00164                 ChangeStateAndNotify( ENotConnected );
00165                 }
00166             break;
00167 
00168         case EListening:
00169                         {
00170             iListenSocket.Close();
00171             if( iStatus.Int() == KErrNone )
00172                 {
00173                 ChangeStateAndNotify( EConnected );
00174                 Read();
00175                 }
00176             else
00177                 {
00178                 ChangeStateAndNotify( ENotConnected );
00179                 }
00180                         }
00181             break;
00182 
00183         case ETimedOut:
00184             if( iStatus.Int() == KErrNone )
00185                 {
00186                 iObserver.SocketState( ETimedOut );
00187                 iState = ENotConnected;
00188                 }
00189             else
00190                 {
00191                 ChangeStateAndNotify( ENotConnected );
00192                 }
00193             break;
00194 
00195         default:
00196             iObserver.SocketState( iStatus.Int() );
00197         }
00198     }
00199 
00200 // -----------------------------------------------------------------------------
00201 // CSIPExSocketEngine::ConnectL
00202 // Connects the socket to the remote host. Asynchronous.
00203 // -----------------------------------------------------------------------------
00204 //
00205 EXPORT_C void CSIPExSocketEngine::ConnectL( 
00206     const TUint32 aIapId, 
00207     const TInetAddr& aIPAddress )
00208     {
00209     if( iState != ENotConnected )
00210         {
00211         return;
00212         }
00213 
00214     // Make first sure that underlying interface is active
00215     StartInterfaceL( aIapId );
00216     
00217         // Open a TCP socket
00218         User::LeaveIfError( iDataSocket.Open( 
00219             iSocketServer, KAfInet, KSockStream, KProtocolInetTcp, iConnection ) );
00220     
00221     iAddress = aIPAddress;
00222         iAddress.SetPort( KGamePort );
00223 
00224     // The Connect() allocate local address automatically if 
00225     // not bind yet.
00226     iDataSocket.Connect( iAddress, iStatus );
00227          
00228     iState = EConnecting;
00229     SetActive();
00230     iTimer->After( KTimeOut );
00231     }
00232 
00233 // -----------------------------------------------------------------------------
00234 // CSIPExSocketEngine::Write
00235 // Starts the asynchronous writing
00236 // -----------------------------------------------------------------------------
00237 //
00238 EXPORT_C void CSIPExSocketEngine::Write( const TDesC8& aTxt )
00239     {
00240     if( iState == EConnected && !iWriter->IsActive() )
00241         {
00242         iWriter->Write( aTxt );
00243         }
00244     }
00245 
00246 // -----------------------------------------------------------------------------
00247 // CSIPExSocketEngine::Read
00248 // Starts the asynchronous reading.
00249 // -----------------------------------------------------------------------------
00250 //
00251 EXPORT_C void CSIPExSocketEngine::Read()
00252     {
00253     if( iState == EConnected && !iReader->IsActive() )
00254         {
00255         iReader->Read();
00256         }
00257     }
00258 
00259 // -----------------------------------------------------------------------------
00260 // CSIPExSocketEngine::Stop
00261 // Cancelling any outstanding read/write request.
00262 // -----------------------------------------------------------------------------
00263 //
00264 EXPORT_C void CSIPExSocketEngine::Stop()
00265     {
00266     switch( iState )
00267         {
00268         case EConnected:
00269                         {
00270             iWriter->Cancel();
00271             iReader->Cancel();
00272             TRequestStatus status;
00273             iDataSocket.Shutdown( RSocket::EImmediate, status );
00274             User::WaitForRequest( status);
00275             iConnection.Close();
00276             ChangeStateAndNotify( ENotConnected );
00277                         }
00278             break;
00279         case EListening:
00280         case EConnecting:
00281             Cancel();
00282             break;
00283         default:
00284             break;
00285         }
00286     }
00287 
00288 // -----------------------------------------------------------------------------
00289 // CSIPExSocketEngine::StartListeningL
00290 // Resolves the local address and starts listening game port. Asynchronous.
00291 // -----------------------------------------------------------------------------
00292 //
00293 EXPORT_C TInetAddr& CSIPExSocketEngine::StartListeningL( const TUint32 aIapId )
00294     {
00295     StartInterfaceL( aIapId );
00296     ResolveLocalIPAddressL();
00297     iAddress.SetPort( KGamePort );
00298     User::LeaveIfError( iListenSocket.Open( 
00299             iSocketServer, KAfInet, KSockStream, KProtocolInetTcp ) );
00300     User::LeaveIfError( iDataSocket.Open( iSocketServer ) );
00301     User::LeaveIfError( iListenSocket.Bind( iAddress ) );
00302     
00303     User::LeaveIfError( iListenSocket.Listen( 1 ) );
00304 
00305     iListenSocket.Accept( iDataSocket, iStatus );    
00306     iState = EListening;
00307     SetActive();
00308 
00309     return iAddress;
00310     }
00311     
00312 // -----------------------------------------------------------------------------
00313 // CSIPExSocketEngine::StartInterfaceL
00314 // Activates PDP ctx
00315 // -----------------------------------------------------------------------------
00316 //
00317 void CSIPExSocketEngine::StartInterfaceL( const TUint32 aIapId )
00318     {
00319     if( !iConnection.SubSessionHandle() )
00320         { 
00321         User::LeaveIfError( iConnection.Open( iSocketServer ) );
00322         }
00323 
00324     TCommDbConnPref prefs;
00325     prefs.SetDialogPreference( ECommDbDialogPrefDoNotPrompt );
00326     prefs.SetDirection( ECommDbConnectionDirectionOutgoing );
00327     prefs.SetIapId( aIapId );
00328 
00329     User::LeaveIfError( iConnection.Start( prefs ) );
00330     }
00331 
00332 // -----------------------------------------------------------------------------
00333 // CSIPExSocketEngine::ResolveLocalIPAddressL
00334 // Resolves the local IP address.
00335 // -----------------------------------------------------------------------------
00336 //
00337 void CSIPExSocketEngine::ResolveLocalIPAddressL()
00338     {
00339     RHostResolver hostResolver;
00340     TNameEntry entry;
00341 
00342     User::LeaveIfError( hostResolver.Open( iSocketServer, KAfInet, 
00343                                           KProtocolInetTcp, iConnection ));
00344     CleanupClosePushL( hostResolver );
00345  
00346     User::LeaveIfError( hostResolver.GetByName( TPtrC(), entry ) );
00347     if ( !TInetAddr::Cast( entry().iAddr ).IsWildAddr() )
00348          {
00349          iAddress = TInetAddr::Cast( entry().iAddr );
00350          }
00351          
00352     CleanupStack::PopAndDestroy(); // hostResolver
00353     }
00354 
00355 // -----------------------------------------------------------------------------
00356 // CSIPExSocketEngine::TimerExpired
00357 // Callback from the timeout notifier. Completes the request with error code
00358 // KErrNone and state ETimedOut.
00359 // -----------------------------------------------------------------------------
00360 //
00361 void CSIPExSocketEngine::TimerExpired()
00362     {
00363     Cancel();
00364         iState = ETimedOut;
00365         
00366     TRequestStatus* status = &iStatus;          
00367     SetActive();
00368         User::RequestComplete( status, KErrNone );
00369     }
00370 
00371 // -----------------------------------------------------------------------------
00372 // CSIPExSocketEngine::MessageReceived
00373 // Notifies the observer.
00374 // -----------------------------------------------------------------------------
00375 //
00376 void CSIPExSocketEngine::MessageReceived( TDesC8& aBuffer )
00377     {
00378     iObserver.SocketData( aBuffer );
00379     }
00380 
00381 // -----------------------------------------------------------------------------
00382 // CSIPExSocketEngine::ErrorInReading
00383 // Completes the request with error code.
00384 // -----------------------------------------------------------------------------
00385 //
00386 void CSIPExSocketEngine::ErrorInReading( TInt aError )
00387     {
00388     TRequestStatus* status = &iStatus;          
00389     SetActive();
00390         User::RequestComplete( status, aError );
00391     }
00392 
00393 // From MWriterNotifier
00394 // -----------------------------------------------------------------------------
00395 // CSIPExSocketEngine::WriteDone
00396 // 
00397 // -----------------------------------------------------------------------------
00398 //
00399 void CSIPExSocketEngine::WriteDone()
00400     {
00401     // Nothing to do
00402     }
00403 
00404 // -----------------------------------------------------------------------------
00405 // CSIPExSocketEngine::ErrorInWriting
00406 // Completes the request with error code.
00407 // -----------------------------------------------------------------------------
00408 //
00409 void CSIPExSocketEngine::ErrorInWriting( TInt aError )
00410     {
00411     TRequestStatus* status = &iStatus;          
00412     SetActive();
00413         User::RequestComplete( status, aError );
00414     }
00415 
00416 // -----------------------------------------------------------------------------
00417 // CSIPExSocketEngine::ChangeStateAndNotify
00418 // Changes new state and notifies observer.
00419 // -----------------------------------------------------------------------------
00420 //
00421 void CSIPExSocketEngine::ChangeStateAndNotify( TSocketEngineState aNewState )
00422     {
00423     iState = aNewState;
00424     iObserver.SocketState( iState );
00425     }
00426 
00427 // End of file

© Nokia 2006

Back to top