|
S60 3rd Edition SDK for Symbian OS Example Applications Guide |
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 |