3 * Copyright (c) 2000-2012 Samsung Electronics Co., Ltd. All Rights Reserved.
5 * This file is part of msg-service.
7 * Contact: Jaeyun Jeong <jyjeong@samsung.com>
8 * Sangkoo Kim <sangkoo.kim@samsung.com>
9 * Seunghwan Lee <sh.cat.lee@samsung.com>
10 * SoonMin Jung <sm0415.jung@samsung.com>
11 * Jae-Young Lee <jy4710.lee@samsung.com>
12 * KeeBum Kim <keebum.kim@samsung.com>
14 * PROPRIETARY/CONFIDENTIAL
16 * This software is the confidential and proprietary information of
17 * SAMSUNG ELECTRONICS ("Confidential Information"). You shall not
18 * disclose such Confidential Information and shall use it only in
19 * accordance with the terms of the license agreement you entered
20 * into with SAMSUNG ELECTRONICS.
22 * SAMSUNG make no representations or warranties about the suitability
23 * of the software, either express or implied, including but not limited
24 * to the implied warranties of merchantability, fitness for a particular
25 * purpose, or non-infringement. SAMSUNG shall not be liable for any
26 * damages suffered by licensee as a result of using, modifying or
27 * distributing this software or its derivatives.
32 #include <curl/curl.h>
33 #include "MmsPluginUserAgent.h"
34 #include "MmsPluginEventHandler.h"
35 #include "MsgGconfWrapper.h"
36 #include "MmsPluginInternal.h"
37 #include "MsgUtilFile.h"
38 #include "MmsPluginCodec.h"
39 #include "MsgException.h"
40 #include "MmsPluginDrm.h"
41 #include "MmsPluginStorage.h"
44 extern MmsHeader mmsHeader;
46 void PRINT_PDU_TYPE(MMS_PDU_TYPE_T pduType)
50 MSG_DEBUG("[SEND_REQ]");
53 MSG_DEBUG("[MMS_SEND_CONF]");
55 case eMMS_RETRIEVE_AUTO:
56 MSG_DEBUG("[MMS_RETRIEVE_AUTO]");
58 case eMMS_RETRIEVE_MANUAL:
59 MSG_DEBUG("[MMS_RETRIEVE_MANUAL]");
61 case eMMS_RETRIEVE_AUTO_CONF:
62 MSG_DEBUG("[MMS_RETRIEVE_AUTO_CONF]");
64 case eMMS_RETRIEVE_MANUAL_CONF:
65 MSG_DEBUG("[MMS_RETRIEVE_MANUAL_CONF]");
67 case eMMS_DELIVERY_IND:
68 MSG_DEBUG("[MMS_DELIVERY_IND]");
70 case eMMS_NOTIFICATION_IND:
71 MSG_DEBUG("[MMS_NOTIFICATION_IND]");
73 case eMMS_NOTIFYRESP_IND:
74 MSG_DEBUG("[MMS_NOTIFYRESP_IND]");
76 case eMMS_ACKNOWLEDGE_IND:
77 MSG_DEBUG("[MMS_ACKNOWLEDGE_IND]");
79 case eMMS_FORWARD_REQ:
80 MSG_DEBUG("[MMS_FORWARD_REQ]");
82 case eMMS_FORWARD_CONF:
83 MSG_DEBUG("[MMS_FORWARD_CONF]");
86 MSG_DEBUG("[MMS_CANCEL_REQ]");
88 case eMMS_CANCEL_CONF:
89 MSG_DEBUG("[MMS_CANCEL_CONF]");
92 MSG_DEBUG("[MMS_DELETE_REQ]");
94 case eMMS_DELETE_CONF:
95 MSG_DEBUG("[MMS_DELETE_CONF]");
97 case eMMS_READREC_IND:
98 MSG_DEBUG("[MMS_READREC_IND]");
100 case eMMS_READORIG_IND:
101 MSG_DEBUG("[MMS_READORIG_IND]");
103 case eMMS_MBOX_STORE_REQ:
104 MSG_DEBUG("[MMS_MBOX_STORE_REQ]");
106 case eMMS_MBOX_STORE_CONF:
107 MSG_DEBUG("[MMS_MBOX_STORE_CONF]");
109 case eMMS_MBOX_VIEW_REQ:
110 MSG_DEBUG("[MMS_MBOX_VIEW_REQ]");
112 case eMMS_MBOX_VIEW_CONF:
113 MSG_DEBUG("[MMS_MBOX_VIEW_CONF]");
115 case eMMS_MBOX_UPLOAD_REQ:
116 MSG_DEBUG("[MMS_MBOX_UPLOAD_REQ]");
118 case eMMS_MBOX_UPLOAD_CONF:
119 MSG_DEBUG("[MMS_MBOX_UPLOAD_CONF]");
121 case eMMS_MBOX_DELETE_REQ:
122 MSG_DEBUG("[MMS_MBOX_DELETE_REQ]");
124 case eMMS_MBOX_DELETE_CONF:
125 MSG_DEBUG("[MMS_MBOX_DELETE_CONF]");
128 MSG_DEBUG("[Unknown PDU Type]");
134 void PRINT_QUEUE_ENTITY(mmsTranQEntity *entity)
136 MSG_DEBUG("Entity: msgId: %d", entity->msgId);
137 MSG_DEBUG("Entity: completed: %d", entity->isCompleted);
138 MSG_DEBUG("Entity: eMmsPduType: %d", entity->eMmsPduType);
139 MSG_DEBUG("Entity: eHttpCmdType: %d", entity->eHttpCmdType);
140 MSG_DEBUG("Entity: GetLen: %d", entity->getDataLen);
141 MSG_DEBUG("Entity: GetData: (%s)", entity->pGetData);
142 MSG_DEBUG("Entity: postLen: %d", entity->postDataLen);
143 MSG_DEBUG("Entity: pPostData: (%s)", entity->pPostData);
146 void updatePduType(mmsTranQEntity *qEntity)
148 switch(qEntity->eMmsPduType) {
150 qEntity->eMmsPduType = eMMS_SEND_CONF;
152 case eMMS_RETRIEVE_AUTO:
153 qEntity->eMmsPduType = eMMS_RETRIEVE_AUTO_CONF;
155 case eMMS_RETRIEVE_MANUAL:
156 qEntity->eMmsPduType = eMMS_RETRIEVE_MANUAL_CONF;
158 case eMMS_RETRIEVE_AUTO_CONF:
159 qEntity->eMmsPduType = eMMS_NOTIFYRESP_IND;
161 case eMMS_READREC_IND:
162 qEntity->eMmsPduType = eMMS_SEND_CONF;
164 case eMMS_READREPORT_REQ:
165 qEntity->eMmsPduType = eMMS_SEND_CONF;
167 case eMMS_RETRIEVE_MANUAL_CONF:
168 qEntity->eMmsPduType = eMMS_ACKNOWLEDGE_IND;
170 case eMMS_DELETE_REQ:
171 qEntity->eMmsPduType = eMMS_DELETE_CONF;
173 case eMMS_FORWARD_REQ:
174 qEntity->eMmsPduType = eMMS_FORWARD_CONF;
176 case eMMS_MBOX_STORE_REQ:
177 qEntity->eMmsPduType = eMMS_MBOX_STORE_CONF;
179 case eMMS_MBOX_VIEW_REQ:
180 qEntity->eMmsPduType = eMMS_MBOX_VIEW_CONF;
182 case eMMS_MBOX_UPLOAD_REQ:
183 qEntity->eMmsPduType = eMMS_MBOX_UPLOAD_CONF;
185 case eMMS_MBOX_DELETE_REQ:
186 qEntity->eMmsPduType = eMMS_MBOX_DELETE_CONF;
189 MSG_DEBUG("Update PDU Type:");
190 PRINT_PDU_TYPE(qEntity->eMmsPduType);
198 MmsPluginUaManager *MmsPluginUaManager::pInstance = NULL;
200 MmsPluginUaManager::MmsPluginUaManager()
206 MmsPluginUaManager::~MmsPluginUaManager()
214 MmsPluginUaManager *MmsPluginUaManager::instance()
217 pInstance = new MmsPluginUaManager();
222 void MmsPluginUaManager::start()
226 MutexLocker lock(mx);
235 MMS_NET_ERROR_T MmsPluginUaManager::submitHandler(mmsTranQEntity *qEntity)
237 MMS_NET_ERROR_T ret = eMMS_UNKNOWN;
240 MSG_DEBUG("request Submit:");
241 PRINT_PDU_TYPE(qEntity->eMmsPduType);
242 PRINT_QUEUE_ENTITY(qEntity);
244 MmsPluginHttpAgent* httpAgent = MmsPluginHttpAgent::instance();
246 while (retryCount < RETRY_MAX) {
247 ret = httpAgent->cmdRequest(qEntity->eHttpCmdType);
250 if (ret == eMMS_HTTP_SENT_SUCCESS) {
251 MSG_DEBUG("Submit request sent");
253 } else if (ret == eMMS_HTTP_ERROR_NETWORK) {
255 MSG_DEBUG("HTTP sent timeout and try again: %d", retryCount);
258 MSG_DEBUG("Unexpected Error %d", ret);
266 MMS_NET_ERROR_T MmsPluginUaManager::waitingConf(mmsTranQEntity *qEntity)
268 MMS_NET_ERROR_T ret = eMMS_HTTP_ERROR_UNKNOWN;
269 MmsPluginHttpAgent *pHttpAgent = MmsPluginHttpAgent::instance();
270 MMS_PLUGIN_HTTP_CONTEXT_S *pMmsPldCd = NULL;
272 pMmsPldCd = pHttpAgent->getMmsPldCd();
274 if (qEntity->pGetData) {
275 free(qEntity->pGetData);
276 qEntity->pGetData = NULL;
278 qEntity->getDataLen = pMmsPldCd->bufOffset;
279 qEntity->pGetData = (char *)calloc(1, pMmsPldCd->bufOffset + 1);
281 memcpy(qEntity->pGetData, pMmsPldCd->final_content_buf, pMmsPldCd->bufOffset);
282 free(pMmsPldCd->final_content_buf);
283 pMmsPldCd->final_content_buf = NULL;
284 pMmsPldCd->bufOffset = 0;
286 MSG_DEBUG("dataLen:%d pData:(%s)", qEntity->getDataLen, qEntity->pGetData);
288 ret = eMMS_HTTP_CONF_SUCCESS;
293 void MmsPluginUaManager::run()
297 MmsPluginCmAgent *cmAgent = MmsPluginCmAgent::instance();
298 MmsPluginHttpAgent *httpAgent = MmsPluginHttpAgent::instance();
301 CURL *session = NULL;
306 if (mmsTranQ.empty()) {
313 if (!(cmAgent->open())) {
314 MSG_DEBUG("Cm Open Failed");
316 // delete all request from reqQEntities
320 httpAgent->SetMMSProfile();
322 while (!mmsTranQ.empty()) {
324 MSG_DEBUG("###### mmsTranQ.size [%d]", mmsTranQ.size());
326 mmsTranQEntity reqEntity;
327 memset(&reqEntity, 0, sizeof(mmsTranQEntity));
329 mmsTranQ.front(&reqEntity);
331 reqEntity.isCompleted = false;
333 PRINT_QUEUE_ENTITY(&reqEntity);
335 if (reqEntity.eMmsPduType == eMMS_RETRIEVE_AUTO) {
336 msgId = reqEntity.msgId;
337 MmsPluginStorage::instance()->updateNetStatus(msgId, MSG_NETWORK_RETRIEVING);
340 if (httpAgent->cmdRequest(eHTTP_CMD_INIT_SESSION) == eMMS_HTTP_SESSION_OPEN_FAILED) {
341 MSG_DEBUG("HTTP session open failed");
344 // delete all request from reqQEntities
349 MSG_DEBUG("\n\n =================== MMS Transaction Start ========================");
352 httpAgent->setSession(&reqEntity);
354 if (submitHandler(&reqEntity) != eMMS_HTTP_SENT_SUCCESS) {
355 MSG_DEBUG("Transaction Error: submit failed");
357 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
358 mmsTranQ.pop_front();
359 //try to next mmsTranQ
363 MSG_DEBUG("submitHandler(&reqEntity) success.");
364 trId = httpAgent->getHttpConfigData()->transactionId;
366 MSG_DEBUG("#### MMS PDU TYPE = %d ####", reqEntity.eMmsPduType);
368 if (reqEntity.eMmsPduType == eMMS_NOTIFYRESP_IND ||
369 reqEntity.eMmsPduType == eMMS_ACKNOWLEDGE_IND ||
370 reqEntity.eMmsPduType == eMMS_READREC_IND ||
371 reqEntity.eMmsPduType == eMMS_CANCEL_CONF) {
372 reqEntity.isCompleted = true;
374 mmsTranQ.pop_front();
376 MSG_DEBUG("Transaction Completed");
379 // change MmsPduType from XXX.req to XXX.conf for waiting
380 MSG_DEBUG("Update Pdutype");
381 updatePduType(&reqEntity);
382 MSG_DEBUG("Waiting Conf");
385 mmsTranQ.pop_front();
387 //////// Waiting Conf //////////////////////
388 MMS_NET_ERROR_T networkErr;
390 if ((networkErr = waitingConf(&reqEntity)) == eMMS_HTTP_CONF_SUCCESS) {
392 char retrievedFilePath[MAX_FULL_PATH_SIZE+1] = {0,};
396 if (processReceivedData(reqEntity.msgId, reqEntity.pGetData, reqEntity.getDataLen, retrievedFilePath) == false) {
397 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
400 } catch (MsgException& e) {
401 MSG_FATAL("%s", e.what());
402 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
405 } catch (exception& e) {
406 MSG_FATAL("%s", e.what());
407 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
411 if (reqEntity.eMmsPduType != (MMS_PDU_TYPE_T)mmsHeader.type) {
412 if (!(reqEntity.eMmsPduType == eMMS_RETRIEVE_MANUAL_CONF && mmsHeader.type == MMS_MSGTYPE_RETRIEVE_CONF)) {
413 MSG_DEBUG("FAIL::type mismatched req:%d received:%d", reqEntity.eMmsPduType, mmsHeader.type);
415 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
420 MSG_DEBUG("conf received successfully");
423 MmsPluginEventHandler::instance()->handleMmsReceivedData(&reqEntity, retrievedFilePath);
424 } catch (MsgException& e) {
425 MSG_FATAL("%s", e.what());
427 } catch (exception& e) {
428 MSG_FATAL("%s", e.what());
432 MsgSettingGetBool(MMS_RECV_DELIVERY_RECEIPT, &bReportAllowed);
434 MSG_DEBUG("conf received successfully -2");
435 MSG_DEBUG("reqEntity.eMmsPduType [%d]", reqEntity.eMmsPduType);
437 // send NotifyResponseInd
438 if (reqEntity.eMmsPduType == eMMS_RETRIEVE_AUTO_CONF) {
439 char filepath[MAX_FULL_PATH_SIZE] = {0};
440 // change MmsPduType for ind or ack
441 // make the PDU and then attach to reqEntity also.
442 updatePduType(&reqEntity);
444 MSG_DEBUG("#### eMmsPduType:%d ####", reqEntity.eMmsPduType);
446 //update http command type & encode m-notify-response-ind
447 reqEntity.eHttpCmdType = eHTTP_CMD_POST_TRANSACTION;
450 MmsPluginInternal::instance()->encodeNotifyRespInd(reqEntity.transactionId, MMS_MSGSTATUS_RETRIEVED, bReportAllowed, filepath);
451 //m-notification-resp-ind encoding if err is not MSG_SUCCESS then should set x-mms-status to deferred
452 if (MsgGetFileSize(filepath, &reqEntity.postDataLen) == false) {
453 MSG_DEBUG("MsgGetFileSize: failed");
456 } catch (MsgException& e) {
457 MSG_FATAL("%s", e.what());
459 } catch (exception& e) {
460 MSG_FATAL("%s", e.what());
464 if (reqEntity.pPostData) {
465 free(reqEntity.pPostData);
466 reqEntity.pPostData = NULL;
469 reqEntity.pPostData = MsgOpenAndReadMmsFile(filepath, 0, -1, &reqEntity.postDataLen);
471 mmsTranQ.push_front(reqEntity);
475 MSG_DEBUG("Submit Ind");
476 } else if (reqEntity.eMmsPduType == eMMS_RETRIEVE_MANUAL_CONF) {
477 /* saved msg trId should be checked */
478 // Send Acknowledge Ind
479 char filepath[MAX_FULL_PATH_SIZE] = {0};
480 // change MmsPduType for ind or ack
481 // make the PDU and then attach to reqEntity also.
482 updatePduType(&reqEntity);
484 MSG_DEBUG("#### eMmsPduType:%d ####", reqEntity.eMmsPduType);
486 //update http command type & encode m-notify-response-ind
487 reqEntity.eHttpCmdType = eHTTP_CMD_POST_TRANSACTION;
490 MmsPluginInternal::instance()->encodeAckInd(reqEntity.transactionId, bReportAllowed, filepath);
491 if (MsgGetFileSize(filepath, &reqEntity.postDataLen) == false) {
492 MSG_DEBUG("MsgGetFileSize: failed");
495 } catch (MsgException& e) {
496 MSG_FATAL("%s", e.what());
498 } catch (exception& e) {
499 MSG_FATAL("%s", e.what());
503 if (reqEntity.pPostData) {
504 free(reqEntity.pPostData);
505 reqEntity.pPostData = NULL;
508 reqEntity.pPostData = MsgOpenAndReadMmsFile(filepath, 0, -1, &reqEntity.postDataLen);
510 mmsTranQ.push_front(reqEntity);
512 remove(filepath); // not ipc
514 MSG_DEBUG("Submit Ack");
516 reqEntity.isCompleted = true;
518 MSG_DEBUG("Transaction complete");
521 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
524 } while (reqEntity.isCompleted == false);
526 MSG_DEBUG("==== MMS Transaction Completed ====\n\n");
528 if (reqEntity.pPostData) {
529 free(reqEntity.pPostData);
530 reqEntity.pPostData = NULL;
533 if (reqEntity.pGetData) {
534 free(reqEntity.pGetData);
535 reqEntity.pGetData = NULL;
538 // Http Session Close
539 httpAgent->clearSession();
548 MSG_DEBUG("CLEANUP");
550 while (!mmsTranQ.empty()) {
551 MSG_DEBUG("clear mmsTranQ");
553 mmsTranQEntity reqEntity;
554 memset(&reqEntity, 0, sizeof(mmsTranQEntity));
556 mmsTranQ.front(&reqEntity);
558 // notify send fail to APP
559 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
561 if (reqEntity.pGetData) {
562 MSG_DEBUG("free pGetData");
563 free(reqEntity.pGetData);
564 reqEntity.pGetData = NULL;
567 if (reqEntity.pPostData) {
568 MSG_DEBUG("free pPostData");
569 free(reqEntity.pPostData);
570 reqEntity.pPostData = NULL;
573 mmsTranQ.pop_front();
577 MutexLocker locker(mx);
585 void MmsPluginUaManager::getMmsPduData(mmsTranQEntity *qEntity)
587 mmsTranQ.front(qEntity);
590 void MmsPluginUaManager::addMmsReqEntity(mmsTranQEntity req)
592 MSG_DEBUG("New MMS Tran Added");
593 mmsTranQ.push_back(req);
599 bool MmsPluginUaManager::processReceivedData(int msgId, char *pRcvdBody, int rcvdBodyLen, char *retrievedFilePath)
603 char fileName[MSG_FILENAME_LEN_MAX] = {0};
606 MSG_DEBUG(":::%d :%s ", rcvdBodyLen, pRcvdBody);
609 _MmsRegisterDecodeBuffer(gszMmsLoadBuf1, gszMmsLoadBuf2, MSG_MMS_DECODE_BUFFER_MAX);
611 if (MsgCreateFileName(fileName) == false)
614 snprintf(retrievedFilePath, MSG_FILEPATH_LEN_MAX, MSG_DATA_PATH"%s", fileName);
616 MSG_DEBUG("retrievedFilePaths [%s]", retrievedFilePath);
619 if (!MsgOpenCreateAndOverwriteFile(retrievedFilePath, (char *)pRcvdBody, rcvdBodyLen)) {
620 MSG_DEBUG( "_MmsUaInitMsgDecoder: creating temporary file failed(msgID=%d)\n", msgId);
624 if (_MmsReadMsgBody(msgId, true, true, retrievedFilePath) == false) {
625 MSG_DEBUG("The MMS Message might include drm contents!!!");
627 #ifdef __SUPPORT_DRM__
628 if (MmsDrm2GetConvertState() == MMS_DRM2_CONVERT_REQUIRED) {
629 bool bRetToConvert = true;
630 MSG_MESSAGE_INFO_S pMsg = {0, };
634 bRetToConvert = MmsDrm2ConvertMsgBody(mmsHeader.msgType.szOrgFilePath);
636 MmsDrm2SetConvertState(MMS_DRM2_CONVERT_FINISH);
639 remove(mmsHeader.msgType.szOrgFilePath);
640 rename(MMS_DECODE_DRM_CONVERTED_TEMP_FILE, mmsHeader.msgType.szOrgFilePath);
642 if (MmsDrm2ReadMsgConvertedBody(&pMsg, true, true, retrievedFilePath) == false) {
643 MSG_DEBUG("MmsLoadMsg:MmsDrm2ReadMsgConvertedBody() returns false\n");
644 goto ERR_MMS_UA_PROCESS_CONF;
655 ERR_MMS_UA_PROCESS_CONF:
658 MmsPluginStorage::instance()->getMmsMessage(&pMsg);
662 _MmsUnregisterDecodeBuffer();
664 #ifdef __SUPPORT_DRM__
665 _MsgFreeDRMInfo(&pMsg->msgType.drmInfo);
667 _MsgFreeBody(&pMsg->msgBody, pMsg->msgType.type);