|
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 |