2 * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved
4 * Licensed under the Apache License, Version 2.0 (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://www.apache.org/licenses/LICENSE-2.0
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 "MsgException.h"
18 #include "MsgUtilFile.h"
19 #include "MsgGconfWrapper.h"
21 #include "MmsPluginDebug.h"
22 #include "MmsPluginUserAgent.h"
23 #include "MmsPluginHttp.h"
24 #include "MmsPluginConnManWrapper.h"
25 #include "MmsPluginEventHandler.h"
26 #include "MmsPluginInternal.h"
27 #include "MmsPluginCodec.h"
28 #include "MmsPluginDrm.h"
29 #include "MmsPluginStorage.h"
30 #include "MmsPluginUtil.h"
32 void PRINT_PDU_TYPE(MMS_PDU_TYPE_T pduType)
36 MSG_DEBUG("[SEND_REQ]");
39 MSG_DEBUG("[MMS_SEND_CONF]");
41 case eMMS_RETRIEVE_AUTO:
42 MSG_DEBUG("[MMS_RETRIEVE_AUTO]");
44 case eMMS_RETRIEVE_MANUAL:
45 MSG_DEBUG("[MMS_RETRIEVE_MANUAL]");
47 case eMMS_RETRIEVE_AUTO_CONF:
48 MSG_DEBUG("[MMS_RETRIEVE_AUTO_CONF]");
50 case eMMS_RETRIEVE_MANUAL_CONF:
51 MSG_DEBUG("[MMS_RETRIEVE_MANUAL_CONF]");
53 case eMMS_DELIVERY_IND:
54 MSG_DEBUG("[MMS_DELIVERY_IND]");
56 case eMMS_NOTIFICATION_IND:
57 MSG_DEBUG("[MMS_NOTIFICATION_IND]");
59 case eMMS_NOTIFYRESP_IND:
60 MSG_DEBUG("[MMS_NOTIFYRESP_IND]");
62 case eMMS_ACKNOWLEDGE_IND:
63 MSG_DEBUG("[MMS_ACKNOWLEDGE_IND]");
65 case eMMS_FORWARD_REQ:
66 MSG_DEBUG("[MMS_FORWARD_REQ]");
68 case eMMS_FORWARD_CONF:
69 MSG_DEBUG("[MMS_FORWARD_CONF]");
72 MSG_DEBUG("[MMS_CANCEL_REQ]");
74 case eMMS_CANCEL_CONF:
75 MSG_DEBUG("[MMS_CANCEL_CONF]");
78 MSG_DEBUG("[MMS_DELETE_REQ]");
80 case eMMS_DELETE_CONF:
81 MSG_DEBUG("[MMS_DELETE_CONF]");
83 case eMMS_READREC_IND:
84 MSG_DEBUG("[MMS_READREC_IND]");
86 case eMMS_READORIG_IND:
87 MSG_DEBUG("[MMS_READORIG_IND]");
89 case eMMS_MBOX_STORE_REQ:
90 MSG_DEBUG("[MMS_MBOX_STORE_REQ]");
92 case eMMS_MBOX_STORE_CONF:
93 MSG_DEBUG("[MMS_MBOX_STORE_CONF]");
95 case eMMS_MBOX_VIEW_REQ:
96 MSG_DEBUG("[MMS_MBOX_VIEW_REQ]");
98 case eMMS_MBOX_VIEW_CONF:
99 MSG_DEBUG("[MMS_MBOX_VIEW_CONF]");
101 case eMMS_MBOX_UPLOAD_REQ:
102 MSG_DEBUG("[MMS_MBOX_UPLOAD_REQ]");
104 case eMMS_MBOX_UPLOAD_CONF:
105 MSG_DEBUG("[MMS_MBOX_UPLOAD_CONF]");
107 case eMMS_MBOX_DELETE_REQ:
108 MSG_DEBUG("[MMS_MBOX_DELETE_REQ]");
110 case eMMS_MBOX_DELETE_CONF:
111 MSG_DEBUG("[MMS_MBOX_DELETE_CONF]");
114 MSG_DEBUG("[Unknown PDU Type]");
120 void PRINT_QUEUE_ENTITY(mmsTranQEntity *entity)
122 MSG_DEBUG("Entity: msgId: %d", entity->msgId);
123 MSG_DEBUG("Entity: completed: %d", entity->isCompleted);
124 MSG_DEBUG("Entity: eMmsPduType: %d", entity->eMmsPduType);
125 MSG_DEBUG("Entity: eHttpCmdType: %d", entity->eHttpCmdType);
126 MSG_DEBUG("Entity: GetLen: %d", entity->getDataLen);
127 MSG_SEC_DEBUG("Entity: GetData: (%s)", entity->pGetData);
128 MSG_DEBUG("Entity: postLen: %d", entity->postDataLen);
129 MSG_DEBUG("Entity: pPostData: (%s)", entity->pPostData);
132 void updatePduType(mmsTranQEntity *qEntity)
134 switch(qEntity->eMmsPduType) {
136 qEntity->eMmsPduType = eMMS_SEND_CONF;
138 case eMMS_RETRIEVE_AUTO:
139 qEntity->eMmsPduType = eMMS_RETRIEVE_AUTO_CONF;
141 case eMMS_RETRIEVE_MANUAL:
142 qEntity->eMmsPduType = eMMS_RETRIEVE_MANUAL_CONF;
144 case eMMS_RETRIEVE_AUTO_CONF:
145 qEntity->eMmsPduType = eMMS_NOTIFYRESP_IND;
147 case eMMS_READREC_IND:
148 qEntity->eMmsPduType = eMMS_SEND_CONF;
150 case eMMS_READREPORT_REQ:
151 qEntity->eMmsPduType = eMMS_READREPORT_CONF;
153 case eMMS_RETRIEVE_MANUAL_CONF:
154 qEntity->eMmsPduType = eMMS_ACKNOWLEDGE_IND;
156 case eMMS_DELETE_REQ:
157 qEntity->eMmsPduType = eMMS_DELETE_CONF;
159 case eMMS_FORWARD_REQ:
160 qEntity->eMmsPduType = eMMS_FORWARD_CONF;
162 case eMMS_MBOX_STORE_REQ:
163 qEntity->eMmsPduType = eMMS_MBOX_STORE_CONF;
165 case eMMS_MBOX_VIEW_REQ:
166 qEntity->eMmsPduType = eMMS_MBOX_VIEW_CONF;
168 case eMMS_MBOX_UPLOAD_REQ:
169 qEntity->eMmsPduType = eMMS_MBOX_UPLOAD_CONF;
171 case eMMS_MBOX_DELETE_REQ:
172 qEntity->eMmsPduType = eMMS_MBOX_DELETE_CONF;
178 MSG_DEBUG("Update PDU Type:");
179 PRINT_PDU_TYPE(qEntity->eMmsPduType);
182 bool compare_func(mmsTranQEntity const &a, mmsTranQEntity const &b)
184 if (a.msgId == b.msgId) {
185 if ((a.eMmsPduType == eMMS_RETRIEVE_MANUAL || a.eMmsPduType == eMMS_RETRIEVE_AUTO)
186 &&(b.eMmsPduType == eMMS_RETRIEVE_MANUAL || b.eMmsPduType == eMMS_RETRIEVE_AUTO)) {
194 bool compare_func_for_removal(mmsTranQEntity const &a, mmsTranQEntity const &b)
196 if (a.reqID == b.reqID &&
197 a.msgId == b.msgId &&
198 a.sessionId == b.sessionId &&
199 a.simId == b.simId) {
205 MmsPluginUaManager *MmsPluginUaManager::pInstance = NULL;
207 MmsPluginUaManager::MmsPluginUaManager()
215 MmsPluginUaManager::~MmsPluginUaManager()
219 MmsPluginUaManager *MmsPluginUaManager::instance()
222 pInstance = new MmsPluginUaManager();
227 void MmsPluginUaManager::start()
229 /* bool bStart = true; */
231 MsgMutexLocker lock(mx);
239 MMS_NET_ERROR_T MmsPluginUaManager::submitHandler(mmsTranQEntity *qEntity)
243 MMS_NET_ERROR_T ret = eMMS_UNKNOWN;
244 http_request_info_s request_info = {};
245 char *http_url = NULL;
246 const char *home_url = NULL;
247 const char *proxy_addr = NULL;
248 const char *dns_list = NULL;
249 const char *interfaceName = NULL;
252 PRINT_PDU_TYPE(qEntity->eMmsPduType);
254 PRINT_QUEUE_ENTITY(qEntity);
256 cm_ret = MmsPluginCmAgent::instance()->getProxyAddr(&proxy_addr);
258 return eMMS_EXCEPTIONAL_ERROR;
260 cm_ret = MmsPluginCmAgent::instance()->getInterfaceName(&interfaceName);
262 return eMMS_EXCEPTIONAL_ERROR;
265 cm_ret = MmsPluginCmAgent::instance()->getHomeUrl(&home_url);
267 return eMMS_EXCEPTIONAL_ERROR;
269 cm_ret = MmsPluginCmAgent::instance()->getDnsAddrList(&dns_list);
271 return eMMS_EXCEPTIONAL_ERROR;
273 memset(&request_info, 0x00, sizeof(request_info));
275 if (qEntity->eHttpCmdType == eHTTP_CMD_POST_TRANSACTION) {
276 request_info.transaction_type = MMS_HTTP_TRANSACTION_TYPE_POST;
278 request_info.url = home_url;
280 request_info.proxy = proxy_addr;
282 request_info.dns_list = dns_list;
284 request_info.interface = interfaceName;
286 request_info.post_data = qEntity->pPostData;
288 request_info.post_data_len = qEntity->postDataLen;
291 request_info.transaction_type = MMS_HTTP_TRANSACTION_TYPE_GET;
293 http_url = (char *)calloc(1, qEntity->getDataLen + 1);
296 memcpy(http_url, qEntity->pGetData, qEntity->getDataLen);
298 request_info.url = http_url;
300 request_info.proxy = proxy_addr;
302 request_info.dns_list = dns_list;
304 request_info.interface = interfaceName;
307 MMS_HTTP_ERROR_E http_ret;
308 MmsPluginHttpAgent* httpAgent = MmsPluginHttpAgent::instance();
309 http_ret = httpAgent->httpRequest(request_info);
311 if (http_ret == MMS_HTTP_ERROR_NONE) {
312 MSG_DEBUG("Submit request sent");
314 if (qEntity->pGetData) {
315 free(qEntity->pGetData);
316 qEntity->pGetData = NULL;
319 qEntity->pGetData = request_info.response_data;
320 qEntity->getDataLen = request_info.response_data_len;
323 bool cm_status = MmsPluginCmAgent::instance()->getCmStatus();
324 if (cm_status == false) {
325 MSG_INFO("PDP disconnected while MMS transaction in progress. cm status [%d]", cm_status);
326 ret = eMMS_CM_DISCONNECTED;
328 MSG_DEBUG("Unexpected Error http_ret = [%d]", http_ret);
329 ret = eMMS_HTTP_ERROR_NETWORK;
340 MMS_NET_ERROR_T MmsPluginUaManager::waitingConf(mmsTranQEntity *qEntity)
342 return eMMS_HTTP_CONF_SUCCESS;
345 void MmsPluginUaManager::run()
349 MmsPluginCmAgent *cmAgent = MmsPluginCmAgent::instance();
353 while (mmsTranQ.empty()) {
358 /* Request CM Open */
359 if (!(cmAgent->open())) {
360 MSG_FATAL("Cm Open Failed");
361 /* delete all request from reqQEntities */
363 int qSize = mmsTranQ.size();
366 MSG_DEBUG("remove an entity from mmsTranQ");
368 mmsTranQEntity reqEntity;
369 memset(&reqEntity, 0, sizeof(mmsTranQEntity));
372 mmsTranQ.front(&reqEntity);
374 /* notify send fail to APP */
375 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
377 if (reqEntity.pGetData) {
378 MSG_DEBUG("free pGetData");
379 free(reqEntity.pGetData);
380 reqEntity.pGetData = NULL;
383 if (reqEntity.pPostData) {
384 MSG_DEBUG("free pPostData");
385 free(reqEntity.pPostData);
386 reqEntity.pPostData = NULL;
389 mmsTranQ.remove(reqEntity, compare_func_for_removal);
390 /* mmsTranQ.pop_front(); */
397 bool transaction = true;
398 while (transaction) {
400 int qSize = mmsTranQ.size();
406 MSG_DEBUG("###### mmsTranQ.size [%d]", qSize);
408 mmsTranQEntity reqEntity;
409 memset(&reqEntity, 0, sizeof(mmsTranQEntity));
412 mmsTranQ.front(&reqEntity);
415 reqEntity.isCompleted = false;
417 PRINT_QUEUE_ENTITY(&reqEntity);
419 /* MMS Transaction */
420 MSG_DEBUG("\n\n =================== MMS Transaction Start ========================");
423 MMS_NET_ERROR_T mms_net_status = submitHandler(&reqEntity);
424 reqEntity.eMmsTransactionStatus = mms_net_status;
425 if (mms_net_status != eMMS_SUCCESS) {
426 MSG_DEBUG("Transaction Error: submit failed");
428 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
430 mmsTranQ.remove(reqEntity, compare_func_for_removal);
431 /* mmsTranQ.pop_front(); */
433 /* try to next mmsTranQ */
437 MSG_DEBUG("submitHandler(&reqEntity) success.");
439 MSG_DEBUG("#### MMS PDU TYPE = %d ####", reqEntity.eMmsPduType);
441 if (reqEntity.eMmsPduType == eMMS_NOTIFYRESP_IND ||
442 reqEntity.eMmsPduType == eMMS_ACKNOWLEDGE_IND ||
443 reqEntity.eMmsPduType == eMMS_READREC_IND ||
444 reqEntity.eMmsPduType == eMMS_CANCEL_CONF) {
445 reqEntity.isCompleted = true;
447 mmsTranQ.remove(reqEntity, compare_func_for_removal);
448 /* mmsTranQ.pop_front(); */
450 MSG_DEBUG("Transaction Completed");
453 /* change MmsPduType from XXX.req to XXX.conf for waiting */
454 MSG_DEBUG("Update Pdutype");
455 updatePduType(&reqEntity);
456 MSG_DEBUG("Waiting Conf");
459 mmsTranQ.remove(reqEntity, compare_func_for_removal);
460 /* mmsTranQ.pop_front(); */
463 MMS_NET_ERROR_T networkErr;
465 if ((networkErr = waitingConf(&reqEntity)) == eMMS_HTTP_CONF_SUCCESS) {
467 char retrievedFilePath[MAX_FULL_PATH_SIZE+1] = {0, };
469 /* process Http data */
471 if (processReceivedData(reqEntity.msgId, reqEntity.pGetData, reqEntity.getDataLen, retrievedFilePath) == false) {
472 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
475 } catch (MsgException& e) {
476 MSG_FATAL("%s", e.what());
477 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
479 } catch (exception& e) {
480 MSG_FATAL("%s", e.what());
481 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
485 if (reqEntity.eMmsPduType != (MMS_PDU_TYPE_T)mmsHeader.type) {
486 if (!(reqEntity.eMmsPduType == eMMS_RETRIEVE_MANUAL_CONF && mmsHeader.type == MMS_MSGTYPE_RETRIEVE_CONF)) {
487 MSG_DEBUG("FAIL::type mismatched req:%d received:%d", reqEntity.eMmsPduType, mmsHeader.type);
489 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
494 MSG_DEBUG("conf received successfully");
496 MmsPluginEventHandler::instance()->handleMmsReceivedData(&reqEntity, retrievedFilePath);
497 } catch (MsgException& e) {
498 MSG_FATAL("%s", e.what());
500 } catch (exception& e) {
501 MSG_FATAL("%s", e.what());
505 if (MsgSettingGetBool(MMS_SEND_REPORT_ALLOWED, &bReportAllowed) != MSG_SUCCESS)
506 MSG_INFO("MsgSettingGetBool() is failed");
508 MSG_DEBUG("conf received successfully -2");
509 MSG_DEBUG("reqEntity.eMmsPduType [%d]", reqEntity.eMmsPduType);
511 /* send NotifyResponseInd */
512 if (reqEntity.eMmsPduType == eMMS_RETRIEVE_AUTO_CONF) {
513 char filepath[MAX_FULL_PATH_SIZE] = {0};
514 /* change MmsPduType for ind or ack */
515 /* make the PDU and then attach to reqEntity also. */
516 updatePduType(&reqEntity);
518 MSG_DEBUG("#### eMmsPduType:%d ####", reqEntity.eMmsPduType);
520 /* update http command type & encode m-notify-response-ind */
521 reqEntity.eHttpCmdType = eHTTP_CMD_POST_TRANSACTION;
524 MmsPluginInternal::instance()->encodeNotifyRespInd(reqEntity.transactionId, MMS_MSGSTATUS_RETRIEVED, bReportAllowed, filepath);
525 /* m-notification-resp-ind encoding if err is not MSG_SUCCESS then should set x-mms-status to deferred */
526 if (MsgGetFileSize(filepath, &reqEntity.postDataLen) == false) {
527 MSG_DEBUG("MsgGetFileSize: failed");
530 } catch (MsgException& e) {
531 MSG_FATAL("%s", e.what());
533 } catch (exception& e) {
534 MSG_FATAL("%s", e.what());
538 if (reqEntity.pPostData) {
539 free(reqEntity.pPostData);
540 reqEntity.pPostData = NULL;
543 reqEntity.pPostData = MsgOpenAndReadMmsFile(filepath, 0, -1, &reqEntity.postDataLen);
545 mmsTranQ.push_front(reqEntity);
547 if (remove(filepath) != 0) {
548 MSG_DEBUG("Error removing file");
551 MSG_DEBUG("Submit Ind");
552 } else if (reqEntity.eMmsPduType == eMMS_RETRIEVE_MANUAL_CONF) {
553 /* saved msg trId should be checked
554 * Send Acknowledge Ind */
555 char filepath[MAX_FULL_PATH_SIZE] = {0};
556 /* change MmsPduType for ind or ack
557 * make the PDU and then attach to reqEntity also. */
558 updatePduType(&reqEntity);
560 MSG_DEBUG("#### eMmsPduType:%d ####", reqEntity.eMmsPduType);
562 /* update http command type & encode m-notify-response-ind */
563 reqEntity.eHttpCmdType = eHTTP_CMD_POST_TRANSACTION;
566 MmsPluginInternal::instance()->encodeAckInd(reqEntity.transactionId, bReportAllowed, filepath);
567 if (MsgGetFileSize(filepath, &reqEntity.postDataLen) == false) {
568 MSG_DEBUG("MsgGetFileSize: failed");
571 } catch (MsgException& e) {
572 MSG_FATAL("%s", e.what());
574 } catch (exception& e) {
575 MSG_FATAL("%s", e.what());
579 if (reqEntity.pPostData) {
580 free(reqEntity.pPostData);
581 reqEntity.pPostData = NULL;
584 reqEntity.pPostData = MsgOpenAndReadMmsFile(filepath, 0, -1, &reqEntity.postDataLen);
586 mmsTranQ.push_front(reqEntity);
588 remove(filepath); /* not ipc */
590 MSG_DEBUG("Submit Ack");
592 reqEntity.isCompleted = true;
594 MSG_DEBUG("Transaction complete");
597 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
600 } while (reqEntity.isCompleted == false);
602 MSG_DEBUG("==== MMS Transaction Completed ====\n\n");
604 if (reqEntity.pPostData) {
605 free(reqEntity.pPostData);
606 reqEntity.pPostData = NULL;
609 if (reqEntity.pGetData) {
610 free(reqEntity.pGetData);
611 reqEntity.pGetData = NULL;
615 /* Request CM Close */
624 void MmsPluginUaManager::getMmsPduData(mmsTranQEntity *qEntity)
627 mmsTranQ.front(qEntity);
631 void MmsPluginUaManager::addMmsReqEntity(mmsTranQEntity *req)
636 mmsTranQEntity reqTmp = {0, };
638 memcpy(&reqTmp, req, sizeof(mmsTranQEntity));
641 if (mmsTranQ.checkExist(reqTmp, compare_func) == true) {
642 MSG_DEBUG("request Already Exist, req_id = %d", reqTmp.msgId);
644 THROW(MsgException::REQ_EXIST_ERROR, "MMS request already exist");
646 mmsTranQ.push_back(reqTmp);
650 MSG_DEBUG("New MMS Tran Added");
653 bool MmsPluginUaManager::processReceivedData(int msgId, char *pRcvdBody, int rcvdBodyLen, char *retrievedFilePath)
657 /* CID 317909 : replacing MSG_FILENAME_LEN_MAX with MAX_FULL_PATH_SIZE as the latter is max length for internal file path
658 * and size of retrievedFilePath in calling function is same i.e. MAX_FULL_PATH_SIZE+1
659 * CID 358483 : Making fileName smaller causes buffer overflow in MsgCreateFileName function.
660 * So We will keep it 1024 as before but only copy 320 out of it which is the size of retrievedFilePath buffer. */
661 char fileName[MSG_FILENAME_LEN_MAX] = {0};
663 MSG_DEBUG(":::%d :%s ", rcvdBodyLen, pRcvdBody);
666 MmsRegisterDecodeBuffer();
668 if (MsgCreateFileName(fileName) == false)
671 /* CID 317909 : replacing MSG_FILENAME_LEN_MAX with MAX_FULL_PATH_SIZE as the latter is max length for internal file path
672 * and size of retrievedFilePath in calling function is same i.e. MAX_FULL_PATH_SIZE+1
673 * snprintf(retrievedFilePath, MSG_FILEPATH_LEN_MAX, "%s%s", MSG_DATA_PATH, fileName); */
674 snprintf(retrievedFilePath, MAX_FULL_PATH_SIZE, "%s%s", MSG_DATA_PATH, fileName);
676 MSG_SEC_INFO("retrievedFilePaths [%s]", retrievedFilePath);
678 /* create temp file */
679 if (!MsgOpenCreateAndOverwriteFile(retrievedFilePath, (char *)pRcvdBody, rcvdBodyLen)) {
680 MSG_ERR("_MmsUaInitMsgDecoder: creating temporary file failed(msgID=%d)\n", msgId);
686 MmsPluginStorage::instance()->getMmsMessage(&pMsg);
688 memset(pMsg, 0, sizeof(MmsMsg));
690 MmsPluginDecoder::instance()->decodeMmsPdu(pMsg, msgId, retrievedFilePath);
692 if (MmsReadMsgBody(msgId, true, true, retrievedFilePath) == false) {
693 MSG_INFO("The MMS Message might include drm contents!!!");
696 MmsPluginStorage::instance()->getMmsMessage(&pMsg);
700 MmsUnregisterDecodeBuffer();
703 MmsReleaseMsgDRMInfo(&pMsg->msgType.drmInfo);
704 MmsReleaseMsgBody(&pMsg->msgBody, pMsg->msgType.type);