2 * Copyright 2012-2013 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.1 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <sys/utsname.h>
19 #include "MsgException.h"
20 #include "MsgUtilFile.h"
21 #include "MsgGconfWrapper.h"
24 #include "MmsPluginDebug.h"
25 #include "MmsPluginUserAgent.h"
26 #include "MmsPluginHttp.h"
27 #include "MmsPluginConnManWrapper.h"
28 #include "MmsPluginEventHandler.h"
29 #include "MmsPluginInternal.h"
30 #include "MmsPluginCodec.h"
31 #include "MmsPluginDrm.h"
32 #include "MmsPluginStorage.h"
34 extern MmsHeader mmsHeader;
36 void PRINT_PDU_TYPE(MMS_PDU_TYPE_T pduType)
40 MSG_DEBUG("[SEND_REQ]");
43 MSG_DEBUG("[MMS_SEND_CONF]");
45 case eMMS_RETRIEVE_AUTO:
46 MSG_DEBUG("[MMS_RETRIEVE_AUTO]");
48 case eMMS_RETRIEVE_MANUAL:
49 MSG_DEBUG("[MMS_RETRIEVE_MANUAL]");
51 case eMMS_RETRIEVE_AUTO_CONF:
52 MSG_DEBUG("[MMS_RETRIEVE_AUTO_CONF]");
54 case eMMS_RETRIEVE_MANUAL_CONF:
55 MSG_DEBUG("[MMS_RETRIEVE_MANUAL_CONF]");
57 case eMMS_DELIVERY_IND:
58 MSG_DEBUG("[MMS_DELIVERY_IND]");
60 case eMMS_NOTIFICATION_IND:
61 MSG_DEBUG("[MMS_NOTIFICATION_IND]");
63 case eMMS_NOTIFYRESP_IND:
64 MSG_DEBUG("[MMS_NOTIFYRESP_IND]");
66 case eMMS_ACKNOWLEDGE_IND:
67 MSG_DEBUG("[MMS_ACKNOWLEDGE_IND]");
69 case eMMS_FORWARD_REQ:
70 MSG_DEBUG("[MMS_FORWARD_REQ]");
72 case eMMS_FORWARD_CONF:
73 MSG_DEBUG("[MMS_FORWARD_CONF]");
76 MSG_DEBUG("[MMS_CANCEL_REQ]");
78 case eMMS_CANCEL_CONF:
79 MSG_DEBUG("[MMS_CANCEL_CONF]");
82 MSG_DEBUG("[MMS_DELETE_REQ]");
84 case eMMS_DELETE_CONF:
85 MSG_DEBUG("[MMS_DELETE_CONF]");
87 case eMMS_READREC_IND:
88 MSG_DEBUG("[MMS_READREC_IND]");
90 case eMMS_READORIG_IND:
91 MSG_DEBUG("[MMS_READORIG_IND]");
93 case eMMS_MBOX_STORE_REQ:
94 MSG_DEBUG("[MMS_MBOX_STORE_REQ]");
96 case eMMS_MBOX_STORE_CONF:
97 MSG_DEBUG("[MMS_MBOX_STORE_CONF]");
99 case eMMS_MBOX_VIEW_REQ:
100 MSG_DEBUG("[MMS_MBOX_VIEW_REQ]");
102 case eMMS_MBOX_VIEW_CONF:
103 MSG_DEBUG("[MMS_MBOX_VIEW_CONF]");
105 case eMMS_MBOX_UPLOAD_REQ:
106 MSG_DEBUG("[MMS_MBOX_UPLOAD_REQ]");
108 case eMMS_MBOX_UPLOAD_CONF:
109 MSG_DEBUG("[MMS_MBOX_UPLOAD_CONF]");
111 case eMMS_MBOX_DELETE_REQ:
112 MSG_DEBUG("[MMS_MBOX_DELETE_REQ]");
114 case eMMS_MBOX_DELETE_CONF:
115 MSG_DEBUG("[MMS_MBOX_DELETE_CONF]");
118 MSG_DEBUG("[Unknown PDU Type]");
124 void PRINT_QUEUE_ENTITY(mmsTranQEntity *entity)
126 MSG_DEBUG("Entity: msgId: %d", entity->msgId);
127 MSG_DEBUG("Entity: completed: %d", entity->isCompleted);
128 MSG_DEBUG("Entity: eMmsPduType: %d", entity->eMmsPduType);
129 MSG_DEBUG("Entity: eHttpCmdType: %d", entity->eHttpCmdType);
130 MSG_DEBUG("Entity: GetLen: %d", entity->getDataLen);
131 MSG_DEBUG("Entity: GetData: (%s)", entity->pGetData);
132 MSG_DEBUG("Entity: postLen: %d", entity->postDataLen);
133 MSG_DEBUG("Entity: pPostData: (%s)", entity->pPostData);
136 void updatePduType(mmsTranQEntity *qEntity)
138 switch(qEntity->eMmsPduType) {
140 qEntity->eMmsPduType = eMMS_SEND_CONF;
142 case eMMS_RETRIEVE_AUTO:
143 qEntity->eMmsPduType = eMMS_RETRIEVE_AUTO_CONF;
145 case eMMS_RETRIEVE_MANUAL:
146 qEntity->eMmsPduType = eMMS_RETRIEVE_MANUAL_CONF;
148 case eMMS_RETRIEVE_AUTO_CONF:
149 qEntity->eMmsPduType = eMMS_NOTIFYRESP_IND;
151 case eMMS_READREC_IND:
152 qEntity->eMmsPduType = eMMS_SEND_CONF;
154 case eMMS_READREPORT_REQ:
155 qEntity->eMmsPduType = eMMS_READREPORT_CONF;
157 case eMMS_RETRIEVE_MANUAL_CONF:
158 qEntity->eMmsPduType = eMMS_ACKNOWLEDGE_IND;
160 case eMMS_DELETE_REQ:
161 qEntity->eMmsPduType = eMMS_DELETE_CONF;
163 case eMMS_FORWARD_REQ:
164 qEntity->eMmsPduType = eMMS_FORWARD_CONF;
166 case eMMS_MBOX_STORE_REQ:
167 qEntity->eMmsPduType = eMMS_MBOX_STORE_CONF;
169 case eMMS_MBOX_VIEW_REQ:
170 qEntity->eMmsPduType = eMMS_MBOX_VIEW_CONF;
172 case eMMS_MBOX_UPLOAD_REQ:
173 qEntity->eMmsPduType = eMMS_MBOX_UPLOAD_CONF;
175 case eMMS_MBOX_DELETE_REQ:
176 qEntity->eMmsPduType = eMMS_MBOX_DELETE_CONF;
182 MSG_DEBUG("Update PDU Type:");
183 PRINT_PDU_TYPE(qEntity->eMmsPduType);
186 MmsPluginUaManager *MmsPluginUaManager::pInstance = NULL;
188 MmsPluginUaManager::MmsPluginUaManager()
194 MmsPluginUaManager::~MmsPluginUaManager()
202 MmsPluginUaManager *MmsPluginUaManager::instance()
205 pInstance = new MmsPluginUaManager();
210 void MmsPluginUaManager::start()
212 // bool bStart = true;
214 MutexLocker lock(mx);
223 MMS_NET_ERROR_T MmsPluginUaManager::submitHandler(mmsTranQEntity *qEntity)
225 MMS_NET_ERROR_T ret = eMMS_UNKNOWN;
228 MSG_DEBUG("request Submit:");
229 PRINT_PDU_TYPE(qEntity->eMmsPduType);
230 PRINT_QUEUE_ENTITY(qEntity);
232 MmsPluginHttpAgent* httpAgent = MmsPluginHttpAgent::instance();
234 while (retryCount < RETRY_MAX) {
235 ret = httpAgent->cmdRequest(qEntity->eHttpCmdType);
238 if (ret == eMMS_HTTP_SENT_SUCCESS) {
239 MSG_DEBUG("Submit request sent");
241 } else if (ret == eMMS_HTTP_ERROR_NETWORK) {
243 MSG_DEBUG("HTTP sent timeout and try again: %d", retryCount);
246 MSG_DEBUG("Unexpected Error %d", ret);
254 MMS_NET_ERROR_T MmsPluginUaManager::waitingConf(mmsTranQEntity *qEntity)
256 MMS_NET_ERROR_T ret = eMMS_HTTP_ERROR_UNKNOWN;
257 MmsPluginHttpAgent *pHttpAgent = MmsPluginHttpAgent::instance();
258 MMS_PLUGIN_HTTP_CONTEXT_S *pMmsPldCd = NULL;
260 pMmsPldCd = pHttpAgent->getMmsPldCd();
262 if (qEntity->pGetData) {
263 free(qEntity->pGetData);
264 qEntity->pGetData = NULL;
266 qEntity->getDataLen = pMmsPldCd->bufOffset;
267 qEntity->pGetData = (char *)calloc(1, pMmsPldCd->bufOffset + 1);
269 memcpy(qEntity->pGetData, pMmsPldCd->final_content_buf, pMmsPldCd->bufOffset);
270 free(pMmsPldCd->final_content_buf);
271 pMmsPldCd->final_content_buf = NULL;
272 pMmsPldCd->bufOffset = 0;
274 MSG_DEBUG("dataLen:%d pData:(%s)", qEntity->getDataLen, qEntity->pGetData);
276 ret = eMMS_HTTP_CONF_SUCCESS;
281 void MmsPluginUaManager::run()
285 MmsPluginCmAgent *cmAgent = MmsPluginCmAgent::instance();
286 MmsPluginHttpAgent *httpAgent = MmsPluginHttpAgent::instance();
289 // CURL *session = NULL;
294 if (mmsTranQ.empty()) {
301 { // Check is it emulator or not.
303 int ret = uname(&buf);
306 MSG_DEBUG("System runs on [%s].", buf.machine);
307 //if (strncmp(buf.machine, "i686", 4) == 0) {
308 if(strcasestr(buf.machine, "emulated")) {
309 MSG_DEBUG("Running on Emulator mode.");
311 int mmsResult = MsgSettingGetInt(VCONFKEY_TELEPHONY_MMS_SENT_STATUS);
313 MSG_DEBUG("MMS result has to be [%d]", mmsResult);
315 while (!mmsTranQ.empty()) {
316 MSG_DEBUG("###### mmsTranQ.size [%d]", mmsTranQ.size());
318 mmsTranQEntity reqEntity;
319 memset(&reqEntity, 0, sizeof(mmsTranQEntity));
321 mmsTranQ.front(&reqEntity);
324 // For MMS send fail.
325 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
326 mmsTranQ.pop_front();
328 // For MMS send success.
329 MSG_DEBUG("conf received successfully");
331 reqEntity.eMmsPduType = eMMS_SEND_CONF;
334 MmsPluginEventHandler::instance()->handleMmsReceivedData(&reqEntity, NULL);
335 } catch (MsgException& e) {
336 MSG_FATAL("%s", e.what());
338 } catch (exception& e) {
339 MSG_FATAL("%s", e.what());
343 mmsTranQ.pop_front();
348 MutexLocker locker(mx);
358 if (!(cmAgent->open())) {
359 MSG_DEBUG("Cm Open Failed");
361 // delete all request from reqQEntities
365 httpAgent->SetMMSProfile();
367 while (!mmsTranQ.empty()) {
369 MSG_DEBUG("###### mmsTranQ.size [%d]", mmsTranQ.size());
371 mmsTranQEntity reqEntity;
372 memset(&reqEntity, 0, sizeof(mmsTranQEntity));
374 mmsTranQ.front(&reqEntity);
376 reqEntity.isCompleted = false;
378 PRINT_QUEUE_ENTITY(&reqEntity);
380 if (reqEntity.eMmsPduType == eMMS_RETRIEVE_AUTO) {
381 msgId = reqEntity.msgId;
382 MmsPluginStorage::instance()->updateNetStatus(msgId, MSG_NETWORK_RETRIEVING);
385 if (httpAgent->cmdRequest(eHTTP_CMD_INIT_SESSION) == eMMS_HTTP_SESSION_OPEN_FAILED) {
386 MSG_DEBUG("HTTP session open failed");
389 // delete all request from reqQEntities
394 MSG_DEBUG("\n\n =================== MMS Transaction Start ========================");
397 httpAgent->setSession(&reqEntity);
399 if (submitHandler(&reqEntity) != eMMS_HTTP_SENT_SUCCESS) {
400 MSG_DEBUG("Transaction Error: submit failed");
402 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
403 mmsTranQ.pop_front();
404 //try to next mmsTranQ
408 MSG_DEBUG("submitHandler(&reqEntity) success.");
409 trId = httpAgent->getHttpConfigData()->transactionId;
411 MSG_DEBUG("#### MMS PDU TYPE = %d ####", reqEntity.eMmsPduType);
413 if (reqEntity.eMmsPduType == eMMS_NOTIFYRESP_IND ||
414 reqEntity.eMmsPduType == eMMS_ACKNOWLEDGE_IND ||
415 reqEntity.eMmsPduType == eMMS_READREC_IND ||
416 reqEntity.eMmsPduType == eMMS_CANCEL_CONF) {
417 reqEntity.isCompleted = true;
419 mmsTranQ.pop_front();
421 MSG_DEBUG("Transaction Completed");
424 // change MmsPduType from XXX.req to XXX.conf for waiting
425 MSG_DEBUG("Update Pdutype");
426 updatePduType(&reqEntity);
427 MSG_DEBUG("Waiting Conf");
430 mmsTranQ.pop_front();
432 //////// Waiting Conf //////////////////////
433 MMS_NET_ERROR_T networkErr;
435 if ((networkErr = waitingConf(&reqEntity)) == eMMS_HTTP_CONF_SUCCESS) {
437 char retrievedFilePath[MAX_FULL_PATH_SIZE+1] = {0,};
441 if (processReceivedData(reqEntity.msgId, reqEntity.pGetData, reqEntity.getDataLen, retrievedFilePath) == false) {
442 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
445 } catch (MsgException& e) {
446 MSG_FATAL("%s", e.what());
447 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
450 } catch (exception& e) {
451 MSG_FATAL("%s", e.what());
452 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
456 if (reqEntity.eMmsPduType != (MMS_PDU_TYPE_T)mmsHeader.type) {
457 if (!(reqEntity.eMmsPduType == eMMS_RETRIEVE_MANUAL_CONF && mmsHeader.type == MMS_MSGTYPE_RETRIEVE_CONF)) {
458 MSG_DEBUG("FAIL::type mismatched req:%d received:%d", reqEntity.eMmsPduType, mmsHeader.type);
460 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
465 MSG_DEBUG("conf received successfully");
468 MmsPluginEventHandler::instance()->handleMmsReceivedData(&reqEntity, retrievedFilePath);
469 } catch (MsgException& e) {
470 MSG_FATAL("%s", e.what());
472 } catch (exception& e) {
473 MSG_FATAL("%s", e.what());
477 MsgSettingGetBool(MMS_RECV_DELIVERY_RECEIPT, &bReportAllowed);
479 MSG_DEBUG("conf received successfully -2");
480 MSG_DEBUG("reqEntity.eMmsPduType [%d]", reqEntity.eMmsPduType);
482 // send NotifyResponseInd
483 if (reqEntity.eMmsPduType == eMMS_RETRIEVE_AUTO_CONF) {
484 char filepath[MAX_FULL_PATH_SIZE] = {0};
485 // change MmsPduType for ind or ack
486 // make the PDU and then attach to reqEntity also.
487 updatePduType(&reqEntity);
489 MSG_DEBUG("#### eMmsPduType:%d ####", reqEntity.eMmsPduType);
491 //update http command type & encode m-notify-response-ind
492 reqEntity.eHttpCmdType = eHTTP_CMD_POST_TRANSACTION;
495 MmsPluginInternal::instance()->encodeNotifyRespInd(reqEntity.transactionId, MMS_MSGSTATUS_RETRIEVED, bReportAllowed, filepath);
496 //m-notification-resp-ind encoding if err is not MSG_SUCCESS then should set x-mms-status to deferred
497 if (MsgGetFileSize(filepath, &reqEntity.postDataLen) == false) {
498 MSG_DEBUG("MsgGetFileSize: failed");
501 } catch (MsgException& e) {
502 MSG_FATAL("%s", e.what());
504 } catch (exception& e) {
505 MSG_FATAL("%s", e.what());
509 if (reqEntity.pPostData) {
510 free(reqEntity.pPostData);
511 reqEntity.pPostData = NULL;
514 reqEntity.pPostData = MsgOpenAndReadMmsFile(filepath, 0, -1, &reqEntity.postDataLen);
516 mmsTranQ.push_front(reqEntity);
520 MSG_DEBUG("Submit Ind");
521 } else if (reqEntity.eMmsPduType == eMMS_RETRIEVE_MANUAL_CONF) {
522 /* saved msg trId should be checked */
523 // Send Acknowledge Ind
524 char filepath[MAX_FULL_PATH_SIZE] = {0};
525 // change MmsPduType for ind or ack
526 // make the PDU and then attach to reqEntity also.
527 updatePduType(&reqEntity);
529 MSG_DEBUG("#### eMmsPduType:%d ####", reqEntity.eMmsPduType);
531 //update http command type & encode m-notify-response-ind
532 reqEntity.eHttpCmdType = eHTTP_CMD_POST_TRANSACTION;
535 MmsPluginInternal::instance()->encodeAckInd(reqEntity.transactionId, bReportAllowed, filepath);
536 if (MsgGetFileSize(filepath, &reqEntity.postDataLen) == false) {
537 MSG_DEBUG("MsgGetFileSize: failed");
540 } catch (MsgException& e) {
541 MSG_FATAL("%s", e.what());
543 } catch (exception& e) {
544 MSG_FATAL("%s", e.what());
548 if (reqEntity.pPostData) {
549 free(reqEntity.pPostData);
550 reqEntity.pPostData = NULL;
553 reqEntity.pPostData = MsgOpenAndReadMmsFile(filepath, 0, -1, &reqEntity.postDataLen);
555 mmsTranQ.push_front(reqEntity);
557 remove(filepath); // not ipc
559 MSG_DEBUG("Submit Ack");
561 reqEntity.isCompleted = true;
563 MSG_DEBUG("Transaction complete");
566 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
569 } while (reqEntity.isCompleted == false);
571 MSG_DEBUG("==== MMS Transaction Completed ====\n\n");
573 if (reqEntity.pPostData) {
574 free(reqEntity.pPostData);
575 reqEntity.pPostData = NULL;
578 if (reqEntity.pGetData) {
579 free(reqEntity.pGetData);
580 reqEntity.pGetData = NULL;
583 // Http Session Close
584 httpAgent->clearSession();
593 MSG_DEBUG("CLEANUP");
595 while (!mmsTranQ.empty()) {
596 MSG_DEBUG("clear mmsTranQ");
598 mmsTranQEntity reqEntity;
599 memset(&reqEntity, 0, sizeof(mmsTranQEntity));
601 mmsTranQ.front(&reqEntity);
603 // notify send fail to APP
604 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
606 if (reqEntity.pGetData) {
607 MSG_DEBUG("free pGetData");
608 free(reqEntity.pGetData);
609 reqEntity.pGetData = NULL;
612 if (reqEntity.pPostData) {
613 MSG_DEBUG("free pPostData");
614 free(reqEntity.pPostData);
615 reqEntity.pPostData = NULL;
618 mmsTranQ.pop_front();
622 MutexLocker locker(mx);
630 void MmsPluginUaManager::getMmsPduData(mmsTranQEntity *qEntity)
632 mmsTranQ.front(qEntity);
635 void MmsPluginUaManager::addMmsReqEntity(mmsTranQEntity req)
637 MSG_DEBUG("New MMS Tran Added");
638 mmsTranQ.push_back(req);
644 bool MmsPluginUaManager::processReceivedData(int msgId, char *pRcvdBody, int rcvdBodyLen, char *retrievedFilePath)
648 char fileName[MSG_FILENAME_LEN_MAX] = {0};
650 MSG_DEBUG(":::%d :%s ", rcvdBodyLen, pRcvdBody);
653 MmsRegisterDecodeBuffer();
655 if (MsgCreateFileName(fileName) == false)
658 snprintf(retrievedFilePath, MSG_FILEPATH_LEN_MAX, MSG_DATA_PATH"%s", fileName);
660 MSG_DEBUG("retrievedFilePaths [%s]", retrievedFilePath);
663 if (!MsgOpenCreateAndOverwriteFile(retrievedFilePath, (char *)pRcvdBody, rcvdBodyLen)) {
664 MSG_DEBUG( "_MmsUaInitMsgDecoder: creating temporary file failed(msgID=%d)\n", msgId);
668 if (MmsReadMsgBody(msgId, true, true, retrievedFilePath) == false) {
669 MSG_DEBUG("The MMS Message might include drm contents!!!");
671 #ifdef __SUPPORT_DRM__
672 if (MmsDrm2GetConvertState() == MMS_DRM2_CONVERT_REQUIRED) {
673 bool bRetToConvert = true;
674 MSG_MESSAGE_INFO_S pMsg = {0, };
678 bRetToConvert = MmsDrm2ConvertMsgBody(mmsHeader.msgType.szOrgFilePath);
680 MmsDrm2SetConvertState(MMS_DRM2_CONVERT_FINISH);
684 ret = remove(mmsHeader.msgType.szOrgFilePath);
686 MSG_DEBUG("remove fail\n");
687 goto ERR_MMS_UA_PROCESS_CONF;
690 ret = rename(MMS_DECODE_DRM_CONVERTED_TEMP_FILE, mmsHeader.msgType.szOrgFilePath);
692 MSG_DEBUG("rename fail\n");
693 goto ERR_MMS_UA_PROCESS_CONF;
696 if (MmsDrm2ReadMsgConvertedBody(&pMsg, true, true, retrievedFilePath) == false) {
697 MSG_DEBUG("MmsLoadMsg:MmsDrm2ReadMsgConvertedBody() returns false\n");
698 goto ERR_MMS_UA_PROCESS_CONF;
709 ERR_MMS_UA_PROCESS_CONF:
712 MmsPluginStorage::instance()->getMmsMessage(&pMsg);
716 MmsUnregisterDecodeBuffer();
718 #ifdef __SUPPORT_DRM__
719 MmsReleaseMsgDRMInfo(&pMsg->msgType.drmInfo);
721 MmsReleaseMsgBody(&pMsg->msgBody, pMsg->msgType.type);