2 * Copyright 2012 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.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.tizenopensource.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.
18 #include <curl/curl.h>
19 #include "MmsPluginUserAgent.h"
20 #include "MmsPluginEventHandler.h"
21 #include "MsgGconfWrapper.h"
22 #include "MmsPluginInternal.h"
23 #include "MsgUtilFile.h"
24 #include "MmsPluginCodec.h"
25 #include "MsgException.h"
26 #include "MmsPluginDrm.h"
27 #include "MmsPluginStorage.h"
30 extern MmsHeader mmsHeader;
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_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 MmsPluginUaManager *MmsPluginUaManager::pInstance = NULL;
184 MmsPluginUaManager::MmsPluginUaManager()
190 MmsPluginUaManager::~MmsPluginUaManager()
198 MmsPluginUaManager *MmsPluginUaManager::instance()
201 pInstance = new MmsPluginUaManager();
206 void MmsPluginUaManager::start()
208 // bool bStart = true;
210 MutexLocker lock(mx);
219 MMS_NET_ERROR_T MmsPluginUaManager::submitHandler(mmsTranQEntity *qEntity)
221 MMS_NET_ERROR_T ret = eMMS_UNKNOWN;
224 MSG_DEBUG("request Submit:");
225 PRINT_PDU_TYPE(qEntity->eMmsPduType);
226 PRINT_QUEUE_ENTITY(qEntity);
228 MmsPluginHttpAgent* httpAgent = MmsPluginHttpAgent::instance();
230 while (retryCount < RETRY_MAX) {
231 ret = httpAgent->cmdRequest(qEntity->eHttpCmdType);
234 if (ret == eMMS_HTTP_SENT_SUCCESS) {
235 MSG_DEBUG("Submit request sent");
237 } else if (ret == eMMS_HTTP_ERROR_NETWORK) {
239 MSG_DEBUG("HTTP sent timeout and try again: %d", retryCount);
242 MSG_DEBUG("Unexpected Error %d", ret);
250 MMS_NET_ERROR_T MmsPluginUaManager::waitingConf(mmsTranQEntity *qEntity)
252 MMS_NET_ERROR_T ret = eMMS_HTTP_ERROR_UNKNOWN;
253 MmsPluginHttpAgent *pHttpAgent = MmsPluginHttpAgent::instance();
254 MMS_PLUGIN_HTTP_CONTEXT_S *pMmsPldCd = NULL;
256 pMmsPldCd = pHttpAgent->getMmsPldCd();
258 if (qEntity->pGetData) {
259 free(qEntity->pGetData);
260 qEntity->pGetData = NULL;
262 qEntity->getDataLen = pMmsPldCd->bufOffset;
263 qEntity->pGetData = (char *)calloc(1, pMmsPldCd->bufOffset + 1);
265 memcpy(qEntity->pGetData, pMmsPldCd->final_content_buf, pMmsPldCd->bufOffset);
266 free(pMmsPldCd->final_content_buf);
267 pMmsPldCd->final_content_buf = NULL;
268 pMmsPldCd->bufOffset = 0;
270 MSG_DEBUG("dataLen:%d pData:(%s)", qEntity->getDataLen, qEntity->pGetData);
272 ret = eMMS_HTTP_CONF_SUCCESS;
277 void MmsPluginUaManager::run()
281 MmsPluginCmAgent *cmAgent = MmsPluginCmAgent::instance();
282 MmsPluginHttpAgent *httpAgent = MmsPluginHttpAgent::instance();
285 // CURL *session = NULL;
290 if (mmsTranQ.empty()) {
297 if (!(cmAgent->open())) {
298 MSG_DEBUG("Cm Open Failed");
300 // delete all request from reqQEntities
304 httpAgent->SetMMSProfile();
306 while (!mmsTranQ.empty()) {
308 MSG_DEBUG("###### mmsTranQ.size [%d]", mmsTranQ.size());
310 mmsTranQEntity reqEntity;
311 memset(&reqEntity, 0, sizeof(mmsTranQEntity));
313 mmsTranQ.front(&reqEntity);
315 reqEntity.isCompleted = false;
317 PRINT_QUEUE_ENTITY(&reqEntity);
319 if (reqEntity.eMmsPduType == eMMS_RETRIEVE_AUTO) {
320 msgId = reqEntity.msgId;
321 MmsPluginStorage::instance()->updateNetStatus(msgId, MSG_NETWORK_RETRIEVING);
324 if (httpAgent->cmdRequest(eHTTP_CMD_INIT_SESSION) == eMMS_HTTP_SESSION_OPEN_FAILED) {
325 MSG_DEBUG("HTTP session open failed");
328 // delete all request from reqQEntities
333 MSG_DEBUG("\n\n =================== MMS Transaction Start ========================");
336 httpAgent->setSession(&reqEntity);
338 if (submitHandler(&reqEntity) != eMMS_HTTP_SENT_SUCCESS) {
339 MSG_DEBUG("Transaction Error: submit failed");
341 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
342 mmsTranQ.pop_front();
343 //try to next mmsTranQ
347 MSG_DEBUG("submitHandler(&reqEntity) success.");
348 trId = httpAgent->getHttpConfigData()->transactionId;
350 MSG_DEBUG("#### MMS PDU TYPE = %d ####", reqEntity.eMmsPduType);
352 if (reqEntity.eMmsPduType == eMMS_NOTIFYRESP_IND ||
353 reqEntity.eMmsPduType == eMMS_ACKNOWLEDGE_IND ||
354 reqEntity.eMmsPduType == eMMS_READREC_IND ||
355 reqEntity.eMmsPduType == eMMS_CANCEL_CONF) {
356 reqEntity.isCompleted = true;
358 mmsTranQ.pop_front();
360 MSG_DEBUG("Transaction Completed");
363 // change MmsPduType from XXX.req to XXX.conf for waiting
364 MSG_DEBUG("Update Pdutype");
365 updatePduType(&reqEntity);
366 MSG_DEBUG("Waiting Conf");
369 mmsTranQ.pop_front();
371 //////// Waiting Conf //////////////////////
372 MMS_NET_ERROR_T networkErr;
374 if ((networkErr = waitingConf(&reqEntity)) == eMMS_HTTP_CONF_SUCCESS) {
376 char retrievedFilePath[MAX_FULL_PATH_SIZE+1] = {0,};
380 if (processReceivedData(reqEntity.msgId, reqEntity.pGetData, reqEntity.getDataLen, retrievedFilePath) == false) {
381 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
384 } catch (MsgException& e) {
385 MSG_FATAL("%s", e.what());
386 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
389 } catch (exception& e) {
390 MSG_FATAL("%s", e.what());
391 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
395 if (reqEntity.eMmsPduType != (MMS_PDU_TYPE_T)mmsHeader.type) {
396 if (!(reqEntity.eMmsPduType == eMMS_RETRIEVE_MANUAL_CONF && mmsHeader.type == MMS_MSGTYPE_RETRIEVE_CONF)) {
397 MSG_DEBUG("FAIL::type mismatched req:%d received:%d", reqEntity.eMmsPduType, mmsHeader.type);
399 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
404 MSG_DEBUG("conf received successfully");
407 MmsPluginEventHandler::instance()->handleMmsReceivedData(&reqEntity, retrievedFilePath);
408 } catch (MsgException& e) {
409 MSG_FATAL("%s", e.what());
411 } catch (exception& e) {
412 MSG_FATAL("%s", e.what());
416 MsgSettingGetBool(MMS_RECV_DELIVERY_RECEIPT, &bReportAllowed);
418 MSG_DEBUG("conf received successfully -2");
419 MSG_DEBUG("reqEntity.eMmsPduType [%d]", reqEntity.eMmsPduType);
421 // send NotifyResponseInd
422 if (reqEntity.eMmsPduType == eMMS_RETRIEVE_AUTO_CONF) {
423 char filepath[MAX_FULL_PATH_SIZE] = {0};
424 // change MmsPduType for ind or ack
425 // make the PDU and then attach to reqEntity also.
426 updatePduType(&reqEntity);
428 MSG_DEBUG("#### eMmsPduType:%d ####", reqEntity.eMmsPduType);
430 //update http command type & encode m-notify-response-ind
431 reqEntity.eHttpCmdType = eHTTP_CMD_POST_TRANSACTION;
434 MmsPluginInternal::instance()->encodeNotifyRespInd(reqEntity.transactionId, MMS_MSGSTATUS_RETRIEVED, bReportAllowed, filepath);
435 //m-notification-resp-ind encoding if err is not MSG_SUCCESS then should set x-mms-status to deferred
436 if (MsgGetFileSize(filepath, &reqEntity.postDataLen) == false) {
437 MSG_DEBUG("MsgGetFileSize: failed");
440 } catch (MsgException& e) {
441 MSG_FATAL("%s", e.what());
443 } catch (exception& e) {
444 MSG_FATAL("%s", e.what());
448 if (reqEntity.pPostData) {
449 free(reqEntity.pPostData);
450 reqEntity.pPostData = NULL;
453 reqEntity.pPostData = MsgOpenAndReadMmsFile(filepath, 0, -1, &reqEntity.postDataLen);
455 mmsTranQ.push_front(reqEntity);
459 MSG_DEBUG("Submit Ind");
460 } else if (reqEntity.eMmsPduType == eMMS_RETRIEVE_MANUAL_CONF) {
461 /* saved msg trId should be checked */
462 // Send Acknowledge Ind
463 char filepath[MAX_FULL_PATH_SIZE] = {0};
464 // change MmsPduType for ind or ack
465 // make the PDU and then attach to reqEntity also.
466 updatePduType(&reqEntity);
468 MSG_DEBUG("#### eMmsPduType:%d ####", reqEntity.eMmsPduType);
470 //update http command type & encode m-notify-response-ind
471 reqEntity.eHttpCmdType = eHTTP_CMD_POST_TRANSACTION;
474 MmsPluginInternal::instance()->encodeAckInd(reqEntity.transactionId, bReportAllowed, filepath);
475 if (MsgGetFileSize(filepath, &reqEntity.postDataLen) == false) {
476 MSG_DEBUG("MsgGetFileSize: failed");
479 } catch (MsgException& e) {
480 MSG_FATAL("%s", e.what());
482 } catch (exception& e) {
483 MSG_FATAL("%s", e.what());
487 if (reqEntity.pPostData) {
488 free(reqEntity.pPostData);
489 reqEntity.pPostData = NULL;
492 reqEntity.pPostData = MsgOpenAndReadMmsFile(filepath, 0, -1, &reqEntity.postDataLen);
494 mmsTranQ.push_front(reqEntity);
496 remove(filepath); // not ipc
498 MSG_DEBUG("Submit Ack");
500 reqEntity.isCompleted = true;
502 MSG_DEBUG("Transaction complete");
505 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
508 } while (reqEntity.isCompleted == false);
510 MSG_DEBUG("==== MMS Transaction Completed ====\n\n");
512 if (reqEntity.pPostData) {
513 free(reqEntity.pPostData);
514 reqEntity.pPostData = NULL;
517 if (reqEntity.pGetData) {
518 free(reqEntity.pGetData);
519 reqEntity.pGetData = NULL;
522 // Http Session Close
523 httpAgent->clearSession();
532 MSG_DEBUG("CLEANUP");
534 while (!mmsTranQ.empty()) {
535 MSG_DEBUG("clear mmsTranQ");
537 mmsTranQEntity reqEntity;
538 memset(&reqEntity, 0, sizeof(mmsTranQEntity));
540 mmsTranQ.front(&reqEntity);
542 // notify send fail to APP
543 MmsPluginEventHandler::instance()->handleMmsError(&reqEntity);
545 if (reqEntity.pGetData) {
546 MSG_DEBUG("free pGetData");
547 free(reqEntity.pGetData);
548 reqEntity.pGetData = NULL;
551 if (reqEntity.pPostData) {
552 MSG_DEBUG("free pPostData");
553 free(reqEntity.pPostData);
554 reqEntity.pPostData = NULL;
557 mmsTranQ.pop_front();
561 MutexLocker locker(mx);
569 void MmsPluginUaManager::getMmsPduData(mmsTranQEntity *qEntity)
571 mmsTranQ.front(qEntity);
574 void MmsPluginUaManager::addMmsReqEntity(mmsTranQEntity req)
576 MSG_DEBUG("New MMS Tran Added");
577 mmsTranQ.push_back(req);
583 bool MmsPluginUaManager::processReceivedData(int msgId, char *pRcvdBody, int rcvdBodyLen, char *retrievedFilePath)
587 char fileName[MSG_FILENAME_LEN_MAX] = {0};
589 MSG_DEBUG(":::%d :%s ", rcvdBodyLen, pRcvdBody);
592 _MmsRegisterDecodeBuffer(gszMmsLoadBuf1, gszMmsLoadBuf2, MSG_MMS_DECODE_BUFFER_MAX);
594 if (MsgCreateFileName(fileName) == false)
597 snprintf(retrievedFilePath, MSG_FILEPATH_LEN_MAX, MSG_DATA_PATH"%s", fileName);
599 MSG_DEBUG("retrievedFilePaths [%s]", retrievedFilePath);
602 if (!MsgOpenCreateAndOverwriteFile(retrievedFilePath, (char *)pRcvdBody, rcvdBodyLen)) {
603 MSG_DEBUG( "_MmsUaInitMsgDecoder: creating temporary file failed(msgID=%d)\n", msgId);
607 if (_MmsReadMsgBody(msgId, true, true, retrievedFilePath) == false) {
608 MSG_DEBUG("The MMS Message might include drm contents!!!");
610 #ifdef __SUPPORT_DRM__
611 if (MmsDrm2GetConvertState() == MMS_DRM2_CONVERT_REQUIRED) {
612 bool bRetToConvert = true;
613 MSG_MESSAGE_INFO_S pMsg = {0, };
617 bRetToConvert = MmsDrm2ConvertMsgBody(mmsHeader.msgType.szOrgFilePath);
619 MmsDrm2SetConvertState(MMS_DRM2_CONVERT_FINISH);
623 ret = remove(mmsHeader.msgType.szOrgFilePath);
625 MSG_DEBUG("remove fail\n");
626 goto ERR_MMS_UA_PROCESS_CONF;
629 ret = rename(MMS_DECODE_DRM_CONVERTED_TEMP_FILE, mmsHeader.msgType.szOrgFilePath);
631 MSG_DEBUG("rename fail\n");
632 goto ERR_MMS_UA_PROCESS_CONF;
635 if (MmsDrm2ReadMsgConvertedBody(&pMsg, true, true, retrievedFilePath) == false) {
636 MSG_DEBUG("MmsLoadMsg:MmsDrm2ReadMsgConvertedBody() returns false\n");
637 goto ERR_MMS_UA_PROCESS_CONF;
648 ERR_MMS_UA_PROCESS_CONF:
651 MmsPluginStorage::instance()->getMmsMessage(&pMsg);
655 _MmsUnregisterDecodeBuffer();
657 #ifdef __SUPPORT_DRM__
658 _MsgFreeDRMInfo(&pMsg->msgType.drmInfo);
660 _MsgFreeBody(&pMsg->msgBody, pMsg->msgType.type);