javaextensions/wma/sms_cbs/pushplugin/cbs/src.s60/cbsserverconnection.cpp
changeset 21 2a9601315dfc
child 23 98ccebc37403
equal deleted inserted replaced
18:e8e63152f320 21:2a9601315dfc
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15  *
       
    16 */
       
    17 
       
    18 #include <fstream>
       
    19 
       
    20 #include "logger.h"
       
    21 #include "monitor.h"
       
    22 #include "pushexception.h"
       
    23 #include "pusherrorcodes.h"
       
    24 #include "applicationinfo.h"
       
    25 #include "cbsserverconnection.h"
       
    26 #include "connectionlistener.h"
       
    27 #include "cbsserverconnectionfactory.h"
       
    28 
       
    29 //custom error code for filter mismatches
       
    30 const TInt KErrDoesNotMatchMessageId = -20012;
       
    31 
       
    32 // Default array granularity, ~half of 15 pages
       
    33 const TInt KDefaultArrayGranularity = 8;
       
    34 
       
    35 using namespace java::util;
       
    36 namespace java
       
    37 {
       
    38 namespace wma
       
    39 {
       
    40 OS_EXPORT CbsServerConnection::CbsServerConnection(const std::wstring& aUri,
       
    41         const std::wstring& aFilter)
       
    42         :CActive(EPriorityStandard),ServerConnectionBase(aUri, aFilter),
       
    43         mCbsMessageReceived(EFalse),mCbsPartiallyReceived(EFalse),
       
    44         mBroadcastMsgAttributePackage(mBroadcastMsgAttributes),
       
    45         mBroadcastPhoneCapsPckg(mBroadcastPhoneCaps)
       
    46 {
       
    47     JELOG2(EWMA);
       
    48     std::wstring port = aUri.substr(KPortFieldStartIndex); // "cbs://:"
       
    49     mPort = JavaCommonUtils::wstringToInt(port);
       
    50     LOG1(EWMA, EInfo, "created CbsServerConnection on ID %d", mPort);
       
    51 }
       
    52 
       
    53 ServerConnection* ServerConnectionBase::getServerConnection(
       
    54     const std::wstring& aUri, const std::wstring& aFilter)
       
    55 {
       
    56     JELOG2(EWMA);
       
    57     CbsServerConnection* cbsConn = new CbsServerConnection(aUri, aFilter);
       
    58     return cbsConn;
       
    59 }
       
    60 
       
    61 CbsServerConnection::~CbsServerConnection()
       
    62 {
       
    63     JELOG2(EWMA);
       
    64     removeDir(mMessageStoreDirName);
       
    65 }
       
    66 
       
    67 void CbsServerConnection::initializeL()
       
    68 {
       
    69     JELOG2(EWMA);
       
    70     TUint32 modemNo = 0;
       
    71     // get the name of the TSY
       
    72     mTsyName = HBufC16::NewL(KCommsDbSvrMaxFieldLength);
       
    73     TPtr tsyPtr(mTsyName->Des());
       
    74 
       
    75     CCommsDatabase* database = CCommsDatabase::NewL(EDatabaseTypeUnspecified);
       
    76     CleanupStack::PushL(database);
       
    77 
       
    78     database->GetGlobalSettingL(TPtrC(MODEM_PHONE_SERVICES_SMS), modemNo);
       
    79 
       
    80     // Now read the TSY name from the modem table record
       
    81     CCommsDbTableView* dbTable = database->OpenViewMatchingUintLC(TPtrC(MODEM),
       
    82                                  TPtrC(COMMDB_ID), modemNo);
       
    83 
       
    84     User::LeaveIfError(dbTable->GotoFirstRecord());
       
    85     dbTable->ReadTextL(TPtrC(MODEM_TSY_NAME), tsyPtr);
       
    86     CleanupStack::PopAndDestroy(dbTable);
       
    87     CleanupStack::PopAndDestroy(database);
       
    88 
       
    89 
       
    90     // Make a connection to RTelServer
       
    91     User::LeaveIfError(mTelServer.Connect());
       
    92     User::LeaveIfError(mTelServer.ShareAuto());
       
    93 
       
    94     User::LeaveIfError(mTelServer.LoadPhoneModule(*mTsyName));
       
    95 
       
    96     // Get the name of the first phone
       
    97     TInt phones;
       
    98     User::LeaveIfError(mTelServer.EnumeratePhones(phones));
       
    99 
       
   100     // Find the one which has the cbs functionality
       
   101 
       
   102     while (phones--)
       
   103     {
       
   104         TName tsyPhone;
       
   105         User::LeaveIfError(mTelServer.GetTsyName(phones, tsyPhone));
       
   106 
       
   107         if (tsyPhone.CompareF(*mTsyName) == KErrNone)
       
   108         {
       
   109             // Get the phone info
       
   110             RTelServer::TPhoneInfo tPhone;
       
   111             User::LeaveIfError(mTelServer.GetPhoneInfo(phones, tPhone));
       
   112             User::LeaveIfError(mMobilePhone.Open(mTelServer, tPhone.iName));
       
   113 
       
   114             // No need to look through any more of the available phones
       
   115             break;
       
   116         }
       
   117     }
       
   118     mCbsMessagePagesData = new(ELeave) CDesCArrayFlat(KDefaultArrayGranularity);
       
   119     mOpenMonitor = Monitor::createMonitor();
       
   120     int result = pthread_mutex_init(&mMutex, 0);
       
   121     if (result == 0)
       
   122     {
       
   123         result = pthread_cond_init(&mCondVar, 0);
       
   124     }
       
   125     if (0 != result)
       
   126     {
       
   127         User::Leave(result);
       
   128     }
       
   129 }
       
   130 
       
   131 void CbsServerConnection::open(ConnectionListener* aListener,
       
   132                                bool aIsAppLaunched)
       
   133 {
       
   134     JELOG2(EWMA);
       
   135     mIsAppLaunched = aIsAppLaunched;
       
   136     CbsServerConnection::open(aListener);
       
   137 }
       
   138 
       
   139 OS_EXPORT void CbsServerConnection::open(ConnectionListener* aListener)
       
   140 {
       
   141     JELOG2(EWMA);
       
   142     int error = 0;
       
   143     mListener = aListener;
       
   144     //If it is push launched Message store will have received cbs messages
       
   145     //notify the listener
       
   146     if (mMessagesOnStore > 0)
       
   147     {
       
   148         mListener->msgArrived();
       
   149         CbsServerConnectionFactory::getFactory().setPendingMsgFlag(mUri, false);
       
   150     }
       
   151     else if (!mIsListening)
       
   152     {
       
   153         TRAP(error, initializeL());
       
   154         if (error != KErrNone)
       
   155         {
       
   156             ELOG1(EWMA, "CBS : Error while Initializing = %d", error);
       
   157             std::string errTxt("ERROR!!! CBS : Error while Initializing");
       
   158             throw PushException(COMMON_SRV_CONN_PLUGIN_ERROR, errTxt, __FILE__,
       
   159                                 __FUNCTION__, __LINE__);
       
   160         }
       
   161         mInitialized = ETrue;
       
   162         // Set up RBroadcastMessaging
       
   163         error = mBroadcastMessage.Open(mMobilePhone);
       
   164         if (error != KErrNone)
       
   165         {
       
   166             ELOG1(EWMA, "CBS : RBroadcastMessaging Open failed : %d", error);
       
   167             std::string errTxt("ERROR!!! CBS :RBroadcastMessaging Open failed");
       
   168             throw PushException(COMMON_SRV_CONN_PLUGIN_ERROR, errTxt, __FILE__,
       
   169                                 __FUNCTION__, __LINE__);
       
   170         }
       
   171         // Get the phone capabilities to find out if it is a GSM or WCDMA
       
   172         // based phone
       
   173         error = mBroadcastMessage.GetCaps(mBroadcastPhoneCapsPckg);
       
   174         if (error != KErrNone)
       
   175         {
       
   176             ELOG1(EWMA, "CBS : Get Capabilities failed : %d", error);
       
   177             std::string errTxt("ERROR!!! CBS: Get Capabilities failed");
       
   178             throw PushException(COMMON_SRV_CONN_PLUGIN_ERROR, errTxt, __FILE__,
       
   179                                 __FUNCTION__, __LINE__);
       
   180         }
       
   181         // If the phone supports CDMA networks, then return KErrNotSupported
       
   182         if ((mBroadcastPhoneCaps.iModeCaps
       
   183                 & RMobileBroadcastMessaging::KCapsCdmaTpduFormat)
       
   184                 == RMobileBroadcastMessaging::KCapsCdmaTpduFormat)
       
   185         {
       
   186             ELOG(EWMA, "CBS : CDMA networks - Not Supported");
       
   187             std::string errTxt("ERROR!!!CBS : CDMA networks - Not Supported");
       
   188             throw PushException(COMMON_SRV_CONN_PLUGIN_ERROR, errTxt, __FILE__,
       
   189                                 __FUNCTION__, __LINE__);
       
   190         }
       
   191         // Create Message Store
       
   192         const java::runtime::ApplicationInfo& appInf =
       
   193             java::runtime::ApplicationInfo::getInstance();
       
   194         const std::wstring& root = appInf.getRootPath();
       
   195         error = createMessageStore(root + CBS_STORE_PATH);
       
   196         if (error != KErrNone)
       
   197         {
       
   198             ELOG1(EWMA,"CBS : create message store failed : %d",error);
       
   199             std::string errTxt("ERROR!!! CBS : create message store failed");
       
   200             throw PushException(COMMON_SRV_CONN_PLUGIN_ERROR,errTxt,__FILE__,
       
   201                                 __FUNCTION__,__LINE__);
       
   202         }
       
   203         mState = ECbsOpen;
       
   204         //Create the listening thread which listens for Cbs messages
       
   205         error = pthread_create(&mThreadId, NULL,
       
   206                                CbsServerConnection::listenThread, this);
       
   207 
       
   208         if (error != KErrNone)
       
   209         {
       
   210             ELOG1(EWMA,"CBS : listenThread creation failed : %d",error);
       
   211             std::string errTxt("ERROR!!! CBS : listenThread creation failed");
       
   212             throw PushException(COMMON_SRV_CONN_PLUGIN_ERROR,errTxt,__FILE__,
       
   213                                 __FUNCTION__,__LINE__);
       
   214         }
       
   215 
       
   216         mOpenMonitor->wait();
       
   217         // If there are any messages already available in the message store
       
   218         // notify the listener
       
   219         if (mMessagesOnStore > 0)
       
   220         {
       
   221             mListener->msgArrived();
       
   222         }
       
   223         mIsListening = true;
       
   224     }
       
   225 }
       
   226 
       
   227 
       
   228 void* CbsServerConnection::listenThread(void* aParams)
       
   229 {
       
   230     JELOG2(EWMA);
       
   231     CTrapCleanup* tc = CTrapCleanup::New();
       
   232     CbsServerConnection* aCbsSrvConn =
       
   233         reinterpret_cast<CbsServerConnection*>(aParams);
       
   234     // As there is no possibility of active scheduler being installed to this
       
   235     // thread prior to this , there is no need for any checks.
       
   236     CActiveScheduler* activeScheduler = new CActiveScheduler();
       
   237     CActiveScheduler::Install(activeScheduler);
       
   238     CActiveScheduler::Add(aCbsSrvConn);
       
   239     aCbsSrvConn->setFilterSettings();
       
   240     aCbsSrvConn->SetActive();
       
   241     (aCbsSrvConn->mOpenMonitor)->notify();
       
   242     activeScheduler->Start();
       
   243     delete activeScheduler;
       
   244     delete tc;
       
   245     return 0;
       
   246 }
       
   247 
       
   248 void CbsServerConnection::setFilterSettings()
       
   249 {
       
   250     JELOG2(EWMA);
       
   251     mBroadcastMessage.SetFilterSetting(iStatus,
       
   252                                        RMobileBroadcastMessaging::EBroadcastAcceptAll);
       
   253 }
       
   254 
       
   255 
       
   256 void CbsServerConnection::startCBSListening()
       
   257 {
       
   258     JELOG2(EWMA);
       
   259     mState = ECbsReceivingActive;
       
   260     mBroadcastMessage.ReceiveMessage(iStatus, mBroadcastPageData,
       
   261                                      mBroadcastMsgAttributePackage);
       
   262 }
       
   263 
       
   264 void CbsServerConnection::DoCancel()
       
   265 {
       
   266     JELOG2(EWMA);
       
   267     // Only cancel the appropriate asynchronous request
       
   268     switch (mState)
       
   269     {
       
   270     case ECbsOpen:
       
   271     {
       
   272         mBroadcastMessage.CancelAsyncRequest(
       
   273             EMobileBroadcastMessagingSetFilterSetting);
       
   274         break;
       
   275     }
       
   276     default:
       
   277     {
       
   278         mBroadcastMessage.CancelAsyncRequest(
       
   279             EMobileBroadcastMessagingReceiveMessage);
       
   280         break;
       
   281     }
       
   282     }
       
   283 }
       
   284 
       
   285 int CbsServerConnection::retrieveMessage(TJavaMessageParametersBuf& aCbsBuf)
       
   286 {
       
   287     JELOG2(EWMA);
       
   288     TCBSParametersBuf cbsParametersBuf;
       
   289     std::wstring path;
       
   290     path += mMessageStoreDirName;
       
   291     try
       
   292     {
       
   293         path += JavaCommonUtils::intToWstring(mFirstMessageInStore);
       
   294         char* messagePath = JavaCommonUtils::wstringToUtf8(path);
       
   295         // Read the CBS file contents
       
   296         readStream.exceptions(std::ifstream::failbit|std::ifstream::badbit);
       
   297 
       
   298         readStream.open(messagePath, std::ios::in | std::ios::binary);
       
   299         readStream.read((char*) cbsParametersBuf.Ptr(), cbsParametersBuf.Size());
       
   300         readStream.read((char*)(aCbsBuf().mData).Ptr(),
       
   301                         cbsParametersBuf().mDataSize);
       
   302         readStream.close();
       
   303         (aCbsBuf().mData).SetLength((cbsParametersBuf().mDataSize)>>1);
       
   304         LOG1(EWMA,EInfo,"WMA : CBS Message Data Length %d",
       
   305              cbsParametersBuf().mDataSize);
       
   306         aCbsBuf().mAddress = cbsParametersBuf().mAddress;
       
   307         aCbsBuf().mPort = 0;
       
   308         // Get encoding
       
   309         aCbsBuf().mEncoding = cbsParametersBuf().mEncoding;
       
   310         deleteMessage();
       
   311         delete[] messagePath;
       
   312     }
       
   313     catch (std::ifstream::failure e)
       
   314     {
       
   315         ELOG(EWMA,"CBS : Exception while opening/reading file");
       
   316         readStream.exceptions(std::ofstream::goodbit);
       
   317         readStream.close();
       
   318         return KErrGeneral;
       
   319     }
       
   320     catch (ExceptionBase ex)
       
   321     {
       
   322         return KErrGeneral;
       
   323     }
       
   324     return KErrNone;
       
   325 }
       
   326 
       
   327 
       
   328 void CbsServerConnection::close()
       
   329 {
       
   330     JELOG2(EWMA);
       
   331     // the close and RunL are synchronized to make it SMP safe.
       
   332     if (mInitialized)
       
   333     {
       
   334         pthread_mutex_lock(&mMutex);
       
   335         mMessagesOnStore = 0;
       
   336         mInitialized = EFalse;
       
   337         mIsListening = false;
       
   338         mIsAppLaunched = false;
       
   339         mCbsMessageReceived = EFalse;
       
   340         mCbsPartiallyReceived = EFalse;
       
   341         if (mState != ECbsReceivingDeactive)
       
   342         {
       
   343             // Cancel blocks, so it is not called. Instead we check for any
       
   344             // outstanding request and call DoCancel().
       
   345             if (IsActive())
       
   346             {
       
   347                 DoCancel();
       
   348             }
       
   349             mState = ECbsReceivingDeactive;
       
   350             if (mRunning)
       
   351             {
       
   352                 pthread_cond_wait(&mCondVar, &mMutex);
       
   353             }
       
   354             mBroadcastMessage.Close();
       
   355             mMobilePhone.Close();
       
   356             mTelServer.Close();
       
   357             mCbsMessagePagesRef.Reset();
       
   358             delete mCbsMessagePagesData; // invokes Reset() if necessary
       
   359             delete mOpenMonitor;
       
   360             delete mTsyName;
       
   361         }
       
   362         pthread_mutex_unlock(&mMutex);
       
   363         pthread_mutex_destroy(&mMutex);
       
   364         pthread_cond_destroy(&mCondVar);
       
   365     }
       
   366 }
       
   367 
       
   368 TInt CbsServerConnection::RunError(TInt aError)
       
   369 {
       
   370     JELOG2(EWMA);
       
   371     mListener->error(mUri, aError, "CBS :Error Receiving Broadcast Message");
       
   372     mRunning = EFalse;
       
   373     pthread_cond_signal(&mCondVar);
       
   374     pthread_mutex_unlock(&mMutex);
       
   375     CActiveScheduler::Stop();
       
   376     return KErrNone;
       
   377 }
       
   378 
       
   379 void CbsServerConnection::RunL()
       
   380 {
       
   381     JELOG2(EWMA);
       
   382     pthread_mutex_lock(&mMutex);
       
   383     if (iStatus.Int() < KErrNone && iStatus.Int() != KErrCancel
       
   384             && mState != ECbsReceivingDeactive)
       
   385     {
       
   386         ELOG1(EWMA,"CBS : Error Receiving Broadcast Message:%d",iStatus.Int());
       
   387         mListener->error(mUri, iStatus.Int(),
       
   388                          "CBS : Error Receiving Broadcast Message");
       
   389         if (mIsAppLaunched)
       
   390         {
       
   391             startCBSListening();
       
   392             SetActive();
       
   393         }
       
   394         else
       
   395         {
       
   396             mRunning = EFalse;
       
   397             pthread_cond_signal(&mCondVar);
       
   398             CActiveScheduler::Stop();
       
   399         }
       
   400         pthread_mutex_unlock(&mMutex);
       
   401         return;
       
   402     }
       
   403     switch (mState)
       
   404     {
       
   405     case ECbsOpen:
       
   406     {
       
   407         mRunning = ETrue;
       
   408         //start listening for cbs messages
       
   409         startCBSListening();
       
   410         SetActive();
       
   411         break;
       
   412     }
       
   413     case ECbsReceivingActive:
       
   414     {
       
   415         TRAPD(error, readMessageFromStackL());
       
   416         if (error != KErrNone)
       
   417         {
       
   418             // port number does not match
       
   419             if (error != KErrDoesNotMatchMessageId)
       
   420             {
       
   421                 // Otherwise report back to client as a system error occurred
       
   422                 mListener->error(mUri, error,
       
   423                                  "CBS : Error Receiving Broadcast Message");
       
   424             }
       
   425         }
       
   426         else
       
   427         {
       
   428             if (mCbsMessageReceived)
       
   429             {
       
   430                 mCbsMessageReceived = EFalse;
       
   431                 // we have a complete message, so notify client
       
   432                 mMessagesOnStore++;
       
   433                 // If listening by push setPendingMsgFlag to true.
       
   434                 // This is required as per push framework , so that
       
   435                 // listConnections & other push calls works fine.
       
   436                 if (!mIsAppLaunched)
       
   437                 {
       
   438                     CbsServerConnectionFactory::getFactory().setPendingMsgFlag(
       
   439                         mUri, true);
       
   440                 }
       
   441                 mListener->msgArrived();
       
   442             }
       
   443         }
       
   444         startCBSListening();
       
   445         SetActive();
       
   446         break;
       
   447     }
       
   448     case ECbsReceivingDeactive:
       
   449     {
       
   450         mRunning = EFalse;
       
   451         pthread_cond_signal(&mCondVar);
       
   452         CActiveScheduler::Stop();
       
   453         break;
       
   454     }
       
   455     default:
       
   456     {
       
   457         //Nothing to do
       
   458     }
       
   459     }
       
   460     pthread_mutex_unlock(&mMutex);
       
   461 }
       
   462 
       
   463 void CbsServerConnection::readMessageFromStackL()
       
   464 {
       
   465     JELOG2(EWMA);
       
   466     // Generate a message decoder
       
   467     CJavaCbsDecoder* cbsDecoder = new CJavaCbsDecoder();
       
   468     CleanupStack::PushL(cbsDecoder);
       
   469 
       
   470     TCBSDataBuf messageData = decodeCbsMessageL(cbsDecoder , mBroadcastPageData);
       
   471     // Filter the message based on the message Id
       
   472     if (mCbsMessageId != mPort)
       
   473     {
       
   474         CleanupStack::PopAndDestroy(cbsDecoder);
       
   475         User::LeaveIfError(KErrDoesNotMatchMessageId);
       
   476     }
       
   477 
       
   478     // Handle the possiblity of the message being a multipage message
       
   479 
       
   480     if (mCbsTotalNumPages != 1)
       
   481     {
       
   482         // This is a part of a multipage message
       
   483 
       
   484         // Get information about the message
       
   485         TInt currentPage = mCbsPageNumber;
       
   486         TUint messageCode = cbsDecoder->getMessageCode();
       
   487 
       
   488         if (mCbsPartiallyReceived)
       
   489         {
       
   490             // check whether or not this is the same one of already received
       
   491             // partial message.
       
   492             if ((messageCode != mCbsMultipageMessageCode) ||(mCbsMessageId
       
   493                     != mCbsMultipageMessageId))
       
   494             {
       
   495                 // This is a new message, so ignore the old one
       
   496                 // and setup for a new multipage message
       
   497 
       
   498                 mCbsMessagePagesData->Reset();
       
   499                 mCbsMessagePagesRef.Reset();
       
   500                 mPageCounter = 0;
       
   501                 mCbsPartiallyReceived = EFalse;
       
   502             }
       
   503         }
       
   504         // Adding more data to a partially saved message
       
   505 
       
   506         // For WCDMA messages, it is assumed that the pages will arrive
       
   507         // in the correct order.  mPageCounter is used to
       
   508         // keep track of the current page number.
       
   509         if (currentPage == KUnknownPageNumber)
       
   510         {
       
   511             currentPage = ++mPageCounter;
       
   512         }
       
   513         if (!mCbsPartiallyReceived)
       
   514         {
       
   515             // Start recording a new multipage message
       
   516             mCbsReceivedPages = (1 << (currentPage - 1));
       
   517             // Set some useful flags
       
   518             mCbsMultipageMessageCode = messageCode;
       
   519             mCbsMultipageMessageId = mCbsMessageId;
       
   520             mCbsPartiallyReceived = ETrue;
       
   521         }
       
   522         // Store the received page number, such that the message can
       
   523         // be reconstructed in the correct order later
       
   524         mCbsMessagePagesRef.Append(currentPage);
       
   525 
       
   526         // Store the actual content of the message
       
   527         mCbsMessagePagesData->AppendL(messageData);
       
   528 
       
   529         // Record which page has been received as a bitmask
       
   530         mCbsReceivedPages |= (1 << (currentPage - 1));
       
   531 
       
   532         // Check if all of the pages have been received
       
   533         if (mCbsReceivedPages == ((static_cast<TUint>
       
   534                                    (1 << mCbsTotalNumPages)) - 1))
       
   535         {
       
   536             // Have received all pages
       
   537             mCbsMessageReceived = ETrue;
       
   538         }
       
   539     }
       
   540     else
       
   541     {
       
   542         // This is a single-paged message
       
   543 
       
   544         if (mCbsPartiallyReceived)
       
   545         {
       
   546             // Reset any existing partially stored multipage message
       
   547             mCbsMessagePagesRef.Reset();
       
   548             mCbsMessagePagesData->Reset();
       
   549             mPageCounter = 0;
       
   550             mCbsPartiallyReceived = EFalse;
       
   551         }
       
   552 
       
   553         mCbsMessageReceived = ETrue;
       
   554     }
       
   555     if (mCbsMessageReceived)
       
   556     {
       
   557         saveCbsMessageL(cbsDecoder->getEncoding(),messageData);
       
   558     }
       
   559     CleanupStack::PopAndDestroy(cbsDecoder);
       
   560 }
       
   561 
       
   562 TCBSDataBuf CbsServerConnection::decodeCbsMessageL(CJavaCbsDecoder* aDecoder,
       
   563         const TDesC8& aData)
       
   564 {
       
   565     JELOG2(EWMA);
       
   566     TUint8 codingScheme =0;
       
   567     TUint16 serialNum =0;
       
   568     const TUint8* data = NULL;
       
   569     //Check whether phone supports GSM/WCDMA
       
   570     if (mBroadcastMsgAttributes.iFormat ==
       
   571             RMobileBroadcastMessaging::EFormatGsmTpdu)
       
   572     {
       
   573         //Get the coding scheme as TUint8 from received cbs message
       
   574         codingScheme = aData[KDataCodingSchemeIndex];
       
   575         //Find the curent PageNumber & TotalNumPages from the message pageInfo.
       
   576         aDecoder->findPageInfo(aData[KPageInfoIndex],mCbsPageNumber,
       
   577                                mCbsTotalNumPages);
       
   578         serialNum = aData[KSerialNumberUpperpart] << 8;
       
   579         serialNum = serialNum | aData[KSerialNumberLowerpart];
       
   580         // Get the Message Identifier for GSM
       
   581         mCbsMessageId = aData[KMessageIdUpperpart] << 8;
       
   582         mCbsMessageId = mCbsMessageId | aData[KMessageIdLowerpart];
       
   583         //Get the Message Data for decode without message Header
       
   584         TInt len = aData.Length();
       
   585         TPtrC8 cbsData = aData.Mid(KGsmHeaderSize, len - KGsmHeaderSize);
       
   586         data = cbsData.Ptr();
       
   587     }
       
   588     else if (mBroadcastMsgAttributes.iFormat ==
       
   589              RMobileBroadcastMessaging::EFormatWcdmaTpdu)
       
   590     {
       
   591         //Get the coding scheme as TUint8 from received cbs message
       
   592         codingScheme = mBroadcastMsgAttributes.iDCS;
       
   593         serialNum = mBroadcastMsgAttributes.iSerialNum;
       
   594         // Get the Message Identifier for wcdma
       
   595         mCbsMessageId = mBroadcastMsgAttributes.iMessageId;
       
   596         //Find the curent PageNumber & TotalNumPages for the Cbs Message
       
   597         mCbsTotalNumPages = mBroadcastMsgAttributes.iNumberOfPages;
       
   598         mCbsPageNumber = KUnknownPageNumber;
       
   599         data = aData.Ptr();
       
   600         // Leave iff total number of messages is greater then Maximum number of
       
   601         // pages supported .
       
   602         if (mCbsTotalNumPages > KMaximumNumOfPages)
       
   603         {
       
   604             User::Leave(KErrGeneral);
       
   605         }
       
   606     }
       
   607     else
       
   608     {
       
   609         //Others are not supported
       
   610         User::Leave(KErrNotSupported);
       
   611     }
       
   612 
       
   613     //Find the message code of the cureent cbs message
       
   614     aDecoder->findMessageCode(serialNum);
       
   615 
       
   616     TCBSDataBuf cbsData;
       
   617     //Decode the message
       
   618     aDecoder->decodeMessageL((TPtrC8)data, cbsData,codingScheme,mFs);
       
   619     return cbsData;
       
   620 }
       
   621 
       
   622 void CbsServerConnection::saveCbsMessageL(TSmsDataCodingScheme::TSmsAlphabet
       
   623         aEncoding,TCBSDataBuf& aMessageData)
       
   624 {
       
   625     JELOG2(EWMA);
       
   626     TCBSParametersBuf cbsParams;
       
   627 
       
   628     HBufC* multipageMessage = NULL;
       
   629 
       
   630     if (!mCbsPartiallyReceived)
       
   631     {
       
   632         // Set the messageData size parameter
       
   633         cbsParams().mDataSize = aMessageData.Size();
       
   634 
       
   635     }
       
   636     else
       
   637     {
       
   638         // The multipage cbs message may arrive in the incorrect order.
       
   639         // Calculate the total length for reconstructed  message
       
   640         TInt totalLength = 0;
       
   641         TUint index =1;
       
   642         while (index <= mCbsTotalNumPages)
       
   643         {
       
   644             TInt pos = mCbsMessagePagesRef.FindL(index);
       
   645             totalLength += (*mCbsMessagePagesData)[pos].Length();
       
   646             index++;
       
   647         }
       
   648         // Create an buffer of sufficient size to hold the entire message
       
   649         multipageMessage = HBufC::NewLC(totalLength);
       
   650         TPtr multipagePtr = multipageMessage->Des();
       
   651 
       
   652         // construct the multipage message
       
   653         index =1;
       
   654         while (index <= mCbsTotalNumPages)
       
   655         {
       
   656             TInt pos = mCbsMessagePagesRef.FindL(index);
       
   657             multipagePtr.Append((*mCbsMessagePagesData)[pos]);
       
   658             index++;
       
   659         }
       
   660         cbsParams().mDataSize = multipageMessage->Size();
       
   661     }
       
   662 
       
   663     // Set the message encoding scheme
       
   664     cbsParams().mEncoding = aEncoding;
       
   665 
       
   666     std::wstring path(mMessageStoreDirName);
       
   667     char* messagePath = 0;
       
   668     std::ofstream writeStream;
       
   669     writeStream.exceptions(std::ofstream::failbit|std::ofstream::badbit);
       
   670     try
       
   671     {
       
   672         path += JavaCommonUtils::intToWstring(mNextMessageInStore);
       
   673         messagePath = JavaCommonUtils::wstringToUtf8(path);
       
   674         writeStream.open(messagePath, std::ios::out | std::ios::binary);
       
   675         writeStream.write((char*) cbsParams.Ptr(), cbsParams.Size());
       
   676         if (mCbsPartiallyReceived)
       
   677         {
       
   678             // Write the generated message to the file
       
   679             writeStream.write((char*) multipageMessage->Ptr(),
       
   680                               multipageMessage->Size());
       
   681         }
       
   682         else
       
   683         {
       
   684             // write the (single-paged) message
       
   685             writeStream.write((char*) aMessageData.Ptr(), aMessageData.Size());
       
   686         }
       
   687         writeStream.close();
       
   688     }
       
   689     catch (std::ofstream::failure e)
       
   690     {
       
   691         ELOG(EWMA,"CBS : Exception while creating/writing file");
       
   692         writeStream.exceptions(std::ofstream::goodbit);
       
   693         writeStream.close();
       
   694         User::Leave(KErrGeneral);
       
   695     }
       
   696     catch (ExceptionBase ex)
       
   697     {
       
   698         User::Leave(KErrGeneral);
       
   699     }
       
   700     delete[] messagePath;
       
   701     if (mCbsPartiallyReceived)
       
   702     {
       
   703         // Cleanup the  received multipage message
       
   704         CleanupStack::PopAndDestroy(multipageMessage);
       
   705         mCbsMessagePagesRef.Reset();
       
   706         mCbsMessagePagesData->Reset();
       
   707         mPageCounter = 0;
       
   708         mCbsPartiallyReceived = EFalse;
       
   709     }
       
   710 
       
   711     if (mFirstMessageInStore == KErrNotFound)
       
   712     {
       
   713         mFirstMessageInStore = mNextMessageInStore;
       
   714     }
       
   715     mNextMessageInStore++;
       
   716 }
       
   717 
       
   718 } // end of namespace wma
       
   719 } // end of namespace java