2 * Copyright (c) 2011 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.
20 * @author Pawel Misiak (p.misiak@samsung.com)
25 #include <dpl/log/log.h>
26 #include <Commons/Exception.h>
27 #include <API/Messaging/ReqReceiverMessage.h>
28 #include "Messaging.h"
29 #include "CallbackMgr.h"
30 #include "MsgServiceHandleMgr.h"
33 #include <MapiStorage.h>
34 #include <MapiMessage.h>
38 using namespace WrtDeviceApis::Messaging;
39 using namespace WrtDeviceApis::Messaging::Api;
42 const char* EMPTY_ID = "0";
45 namespace WrtDeviceApis {
47 Sms::Sms(const string& id) :
52 LogDebug("m_id=" << getIdRef());
53 LogDebug("m_msgType=" << getMessageType());
55 if (getIdRef().empty()) {
58 readExistingMessage();
69 // release platform message structure
70 msg_release_message(&m_messageData);
74 void Sms::update(bool draftsOnly)
76 LogDebug("updating m_id=" << getIdRef());
79 //error if platform message not exists
80 LogError("message can not be updated");
81 Throw(Commons::PlatformException);
85 if (!draftsOnly || getCurrentFolder() == Api::DRAFTBOX) {
89 updateSourceAddress();
94 void Sms::readAllData()
96 readExistingMessage();
99 void Sms::moveToFolder(const FolderType newFolder)
105 const MSG_FOLDER_ID_T platfromFolderId =
106 Messaging::convertFolderToPlatform(newFolder);
108 //call platform api to move message to other folder
109 if (msg_move_msg_to_folder(MsgGetCommonHandle(), convertId(getId()),
110 platfromFolderId) != MSG_SUCCESS) {
111 Throw(Commons::PlatformException);
115 Catch(Commons::PlatformException) {
116 LogError("remove message error");
121 void Sms::moveToFolder(const std::string& /*newFolder*/)
127 void Sms::copyToFolder(const FolderType newFolder)
131 msg_message_t msg = msg_new_message();
135 MSG_SENDINGOPT_S option;
136 memset(&option, 0, sizeof(MSG_SENDINGOPT_S));
137 option.option.smsSendOpt.bReplyPath = true;
138 // trying to get message from platform
140 msg_get_message(MsgGetCommonHandle(), convertId(getIdRef()), msg,
143 const MSG_FOLDER_ID_T platfromFolderId =
144 Messaging::convertFolderToPlatform(newFolder);
145 // new id will me set (initialize to 0)
146 msg_set_message_id(msg, 0);
147 msg_set_folder_id(msg, platfromFolderId);
149 // trying to add message
150 int error = msg_add_message(MsgGetCommonHandle(), msg, &option);
151 if (error != MSG_SUCCESS) {
152 LogError("msg_add_message failed, error code=" << error);
153 Throw(Commons::PlatformException);
156 //releasing platform message structure
157 msg_release_message(&msg);
161 Catch(Commons::PlatformException) {
162 LogError("remove message error");
164 //releasing platform message structure
165 msg_release_message(&msg);
171 void Sms::copyToFolder(const std::string& /*newFolder*/)
179 LogDebug("sending message, id=" << getIdRef());
181 //prepare for sending sms
185 LogDebug("Start Sending Message...");
186 LogDebug("msgId=" << msg_get_message_id(m_messageData));
187 LogDebug("subject: " << msg_get_subject(m_messageData));
188 LogDebug("recipient count: " << msg_get_address_count(m_messageData));
192 for (int i = 0; i < msg_get_address_count(m_messageData); ++i) {
193 if (MSG_RECIPIENTS_TYPE_TO !=
194 msg_get_ith_recipient_type(m_messageData, i))
198 msg_message_t msg = createNewCopyOfPLatformMsg(m_messageData);
200 // remove all addresses except ith
201 msg_reset_address(msg);
202 const char* to = msg_get_ith_address(m_messageData, i);
203 msg_add_address(msg, to, MSG_RECIPIENTS_TYPE_TO);
205 LogDebug("recipient: " << msg_get_ith_address(msg, 0));
206 LogDebug("body: " << msg_sms_get_message_body(msg));
211 DPL::Mutex::ScopedLock lock(&m_mutex);
212 m_sendRequests.push(req);
217 LogDebug("sending method finished");
220 void Sms::sendingCallback(MSG_SENT_STATUS_S *sent_status)
223 "sendingCallback callback received. Req id = " <<
224 sent_status->reqId << " Status = " << (int)sent_status->status <<
225 ", Recipient=" << getRecipient());
227 DPL::Mutex::ScopedLock lock(&m_mutex);
228 if (sent_status->status != MSG_NETWORK_SEND_SUCCESS)
230 m_sendRequests.front().failed = true; // TODO mutex
231 //send callback, error for recipient
232 setSendingStatusFailed();
236 setSendingStatusOk();
238 msg_release_message(¤tQueue().front());
239 currentQueue().pop();
241 //schedule another sub message send
245 void Sms::OnEventReceived(const int&)
252 Api::FolderType Sms::toFolder(const std::string &folder)
254 if (folder == "INBOX") {
256 } else if (folder == "OUTBOX") {
258 } else if (folder == "SENTBOX") {
260 } else if (folder == "DRAFTBOX") {
263 ThrowMsg(Commons::PlatformException, "Invalid folder");
266 void Sms::sendSubMessage()
270 DPL::Mutex::ScopedLock lock(&m_mutex);
272 // if current request queue gets empty, try next one
273 while (!m_sendRequests.empty()) {
274 // send as long as the sending fails until there are no more messages
275 for (MSG_ERROR_T err = MSG_ERR_UNKNOWN;
276 err != MSG_SUCCESS && !currentQueue().empty();)
278 err = CallbackMgrSingleton::Instance().registerAndSend(
279 msg_sms_send_message,
280 currentQueue().front(),
282 LogInfo("Sending Message (submit request) result:" << err);
283 if (err != MSG_SUCCESS) {
285 "Sending Message (submit request) failed!!! err=" << err);
286 msg_release_message(¤tQueue().front());
287 currentQueue().pop();
288 m_sendRequests.front().failed = true;
289 //send callback, error for recipient
290 setSendingStatusFailed();
294 // empty queue -> notify about results
295 if (currentQueue().empty()) {
296 auto event = getSendMessageEvent();
297 if (m_sendRequests.front().failed)
299 event->setExceptionCode(
300 Commons::ExceptionCodes::UnknownException);
303 ReqReceiverMessage *requestReceiver = getRequestReceiver();
307 Commons::EventRequestReceiver<EventSendMessage>::
311 // this request is finished, try next one
312 m_sendRequests.pop();
319 void Sms::setSendingStatusOk()
322 //success callback should be executed here
323 ReqReceiverMessage *requestReceiver = getRequestReceiver();
324 if (requestReceiver) {
325 LogInfo("calling JS success callback");
326 EventSendMessagePtr event = getSendMessageEvent();
327 event->addRecipientSendResult(getRecipient(), true);
331 void Sms::setSendingStatusFailed()
334 //error callback should be executed here
335 EventOnSendingFailedEmitterPtr emitter = getEmitter();
337 EventOnSendingFailedPtr event(new EventOnSendingFailed);
338 event->setError(EventOnSendingFailed::UNKNOWN); // TODO error codes
339 emitter->emit(event);
341 ReqReceiverMessage *requestReceiver = getRequestReceiver();
342 if (requestReceiver) {
343 LogError("calling JS error callback");
344 EventSendMessagePtr event = getSendMessageEvent();
345 event->addRecipientSendResult(getRecipient(), false);
354 // delete message from platform
355 if (msg_delete_message(MsgGetCommonHandle(),
356 convertId(getId())) != MSG_SUCCESS)
358 LogError("delete message failed");
359 Throw(Commons::PlatformException);
361 LogDebug("message deleted succesfully");
365 Catch(Commons::PlatformException) {
366 LogError("remove message error");
371 void Sms::createNewMessage()
374 // release platform message if it was created previously
375 msg_release_message(&m_messageData);
376 m_messageData = NULL;
378 // create new platform message
379 m_messageData = msg_new_message();
382 MSG_SENDINGOPT_S option;
383 memset(&option, 0, sizeof(MSG_SENDINGOPT_S));
384 option.option.smsSendOpt.bReplyPath = true;
386 //default message initialization
387 msg_set_message_id(m_messageData, 0); // It should be set 0
388 msg_set_folder_id(m_messageData, MSG_DRAFT_ID);
389 msg_set_message_type(m_messageData, MSG_TYPE_SMS);
390 msg_set_storage_id(m_messageData, MSG_STORAGE_PHONE);
391 msg_set_network_status(m_messageData, MSG_NETWORK_NOT_SEND);
397 tm dateT = getDateTime();
398 msg_set_time(m_messageData, mktime(&dateT));
400 LogDebug("Message created successfully, msgId=" << getId());
403 Catch(Commons::PlatformException) {
404 LogError("Problem with message creation, cleaning");
408 void Sms::readExistingMessage()
410 if (getIdRef().empty() || (EMPTY_ID == getIdRef())) {
411 ThrowMsg(Commons::PlatformException, "Empty id.");
415 MSG_SENDINGOPT_S option;
416 memset(&option, 0, sizeof(MSG_SENDINGOPT_S));
417 option.option.smsSendOpt.bReplyPath = true;
420 msg_release_message(&m_messageData);
421 m_messageData = NULL;
422 // create new platform structure
423 m_messageData = msg_new_message();
425 MSG_MESSAGE_ID_T l_id = convertId(getIdRef());
426 LogDebug("reading message id=" << l_id);
427 // trying to get message from platform
429 msg_get_message(MsgGetCommonHandle(), l_id, m_messageData,
432 LogDebug("message found with msgId=" << getIdRef());
434 // read all mms dat to abstraction layer
435 readRecipientList(m_messageData);
436 readBody(m_messageData);
437 readFolder(m_messageData);
438 readDateTime(m_messageData);
439 readReadStatus(m_messageData);
440 readSize(m_messageData);
442 LogError("message not found with msgId=" << getIdRef());
446 Catch(Commons::PlatformException) {
451 void Sms::updateBody()
453 // check if abstraction body value has been changed
457 LogInfo("updating platfoprm body");
459 // change body value in platform structure
460 msg_sms_set_message_body(m_messageData, getBodyRef().c_str(),
461 getBodyRef().length());
463 // set flag as true - platform synchronized with abstraction
464 setBodyValidity(true);
469 // check if abstraction recipient (to) value has been changed
470 if (getToRecipients().isValid()) {
473 LogInfo("updating platform to");
475 // change recipient value in platform structure
476 msg_reset_address(m_messageData);
477 vector<string> to = getToRecipients().getRecipients();
478 LogInfo("updating to");
479 for (size_t i = 0; i < to.size(); i++) {
480 if (i >= MAX_TO_ADDRESS_CNT) {
481 LogError("max number of recipient exceeded");
484 LogDebug("adding to[" << i << "]=" << to[i]);
485 string tmpAddr = to[i];
486 // function for validating phone number
487 if (validatePhoneNumber(tmpAddr)) {
488 // add phone number to platform message struncture
489 if (msg_add_address(m_messageData, tmpAddr.c_str(),
490 MSG_RECIPIENTS_TYPE_TO) != MSG_SUCCESS)
492 LogError("problem witgh add address");
493 Throw(Commons::PlatformException);
496 //nothing to do if wrong format
497 LogError("wrong phone number format");
501 // set flag as true - platform synchronized with abstraction
505 void Sms::updateFrom()
507 // check if abstraction from field value has been changed
508 if (getFromValidity()) {
509 // do not update if not changed
512 LogInfo("updating platform from");
516 // set flag as true - platform synchronized with abstraction
517 setFromValidity(true);
520 void Sms::updateSourceAddress()
522 // check if abstraction source address value has been changed
523 if (getSourceAddressValidity()) {
524 // do not update if not changed
527 LogInfo("updating platform source address");
531 // set flag as true - platform synchronized with abstraction
532 setSourceAddressValidity(true);
535 void Sms::updateReadStatus()
537 LogInfo("updating platform read status: " << isRead());
538 if (isReadStatusValid()) {
539 // do not update if not changed
543 if (MSG_SUCCESS != msg_set_read_status(m_messageData, isRead())) {
544 LogError("problem with setting subject");
545 ThrowMsg(Commons::PlatformException, "Problem with setting subject");
547 setReadStatusValidity(true);
550 void Sms::readRecipientList(msg_message_t& messageData)
552 LogDebug("Adding recipients to message, count=" <<
553 msg_get_address_count(messageData));
554 // iterate for all address and store in abstraction
555 for (int i = 0; i < msg_get_address_count(messageData); i++) {
556 string tmp = msg_get_ith_address(messageData, i);
557 int type = msg_get_direction_info(messageData);
559 if (MSG_DIRECTION_TYPE_MT == type) {
560 if (validatePhoneNumber(tmp)) {
561 setSourceAddress(tmp);
564 } else if (MSG_DIRECTION_TYPE_MO == type) {
565 appendToRecipients(tmp);
567 ThrowMsg(Commons::PlatformException, "Wrong type of recipient.");
572 void Sms::readBody(msg_message_t& messageData)
574 //set abstraction body value
575 const char* body = msg_sms_get_message_body(messageData);
577 ThrowMsg(Commons::PlatformException,
578 "Body is NULL. Probably message is invalid.");
583 void Sms::readFolder(msg_message_t& messageData)
585 switch (msg_get_folder_id(messageData)) {
587 setFolderType(Api::INBOX);
590 setFolderType(Api::OUTBOX);
593 setFolderType(Api::SENTBOX);
596 setFolderType(Api::DRAFTBOX);
599 setFolderType(Api::SPAMBOX);
602 LogError("Wrong folder id");
603 ThrowMsg(Commons::PlatformException, "Unsupported folder id.");
607 void Sms::readDateTime(msg_message_t& messageData)
609 tm* time = localtime(msg_get_time(messageData));
611 LogError("localtime failed");
612 Throw(Commons::PlatformException);
617 void Sms::readReadStatus(msg_message_t& messageData)
620 setReadStatus(msg_is_read(messageData));
623 void Sms::readSize(msg_message_t& messageData)
625 setSize(msg_get_message_body_size(messageData));
628 msg_message_t Sms::createNewCopyOfPLatformMsg(const msg_message_t src) const
630 msg_message_t msg = msg_new_message();
632 msg_set_message_id(msg, 0);
633 msg_set_storage_id(msg, msg_get_storage_id(src));
634 msg_set_message_type(msg, msg_get_message_type(src));
635 msg_set_folder_id(msg, msg_get_folder_id(src));
636 for (int i = 0; i < msg_get_address_count(src); i++) {
637 msg_add_address(msg, msg_get_ith_address(src,
639 msg_get_ith_recipient_type(src, i));
641 msg_sms_set_message_body(msg, msg_sms_get_message_body(
642 src), msg_get_message_body_size(src));
643 msg_set_subject(msg, msg_get_subject(src));
644 msg_set_time(msg, *msg_get_time(src));
645 msg_set_network_status(msg, msg_get_network_status(src));
646 msg_set_encode_type(msg, msg_get_encode_type(src));
647 msg_set_read_status(msg, msg_is_read(src));
648 msg_set_protect_status(msg, msg_is_protected(src));
649 msg_set_priority_info(msg, msg_get_priority_info(src));
650 msg_set_direction_info(msg, msg_get_direction_info(src));
651 msg_set_port(msg, msg_get_dest_port(src), msg_get_src_port(src));
652 msg_set_scheduled_time(msg, *msg_get_scheduled_time(src));