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