Merge branch 'sdk'
[platform/core/messaging/msg-service.git] / plugin / sms_plugin / SmsPluginTransport.cpp
1 /*
2 * Copyright 2012  Samsung Electronics Co., Ltd
3 *
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
7 *
8 *    http://www.tizenopensource.org/license
9 *
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.
15 */
16
17 #include <errno.h>
18 #include <math.h>
19
20 #include "MsgDebug.h"
21 #include "MsgCppTypes.h"
22 #include "MsgException.h"
23 #include "MsgGconfWrapper.h"
24 #include "MsgNotificationWrapper.h"
25 #include "MsgUtilFile.h"
26 #include "SmsPluginParamCodec.h"
27 #include "SmsPluginTpduCodec.h"
28 #include "SmsPluginEventHandler.h"
29 #include "SmsPluginStorage.h"
30 #include "SmsPluginCallback.h"
31 #include "SmsPluginTransport.h"
32
33 extern "C"
34 {
35         #include <ITapiNetText.h>
36 }
37
38 #define MSG_DEBUG_BY_FILE
39
40 extern struct tapi_handle *pTapiHandle;
41
42 /*==================================================================================================
43                                      IMPLEMENTATION OF SmsPluginTransport - Member Functions
44 ==================================================================================================*/
45 SmsPluginTransport* SmsPluginTransport::pInstance = NULL;
46
47
48 SmsPluginTransport::SmsPluginTransport()
49 {
50         msgRef          = 0x00;
51         msgRef8bit      = 0x00;
52         msgRef16bit     = 0x0000;
53 }
54
55
56 SmsPluginTransport::~SmsPluginTransport()
57 {
58
59 }
60
61
62 SmsPluginTransport* SmsPluginTransport::instance()
63 {
64         if (!pInstance)
65                 pInstance = new SmsPluginTransport();
66
67         return pInstance;
68 }
69
70
71 void SmsPluginTransport::submitRequest(SMS_REQUEST_INFO_S *pReqInfo)
72 {
73         MSG_BEGIN();
74
75         SMS_TPDU_S tpdu;
76
77         tpdu.tpduType = SMS_TPDU_SUBMIT;
78
79         // Set SMS Send Options - Setting
80         setSmsSendOptions(&(tpdu.data.submit));
81
82         // Set SMS Send Options - Each Message
83         if (pReqInfo->sendOptInfo.bSetting == true)
84         {
85                 tpdu.data.submit.bStatusReport = pReqInfo->sendOptInfo.bDeliverReq;
86                 tpdu.data.submit.bReplyPath = pReqInfo->sendOptInfo.option.smsSendOptInfo.bReplyPath;
87         }
88
89         // Set Coding Scheme for apps that use port number
90         if (pReqInfo->msgInfo.msgPort.valid == true)
91         {
92                 tpdu.data.submit.dcs.codingScheme = (SMS_CODING_SCHEME_T)pReqInfo->msgInfo.encodeType;
93
94                 MSG_DEBUG("DCS is changed by application : [%d]", tpdu.data.submit.dcs.codingScheme);
95         }
96
97         // Set SMSC Options
98         SMS_ADDRESS_S smsc;
99         setSmscOptions(&smsc);
100         int i = 0;
101         int j = 0;
102
103         MSG_DEBUG("pReqInfo->msgInfo.nAddressCnt [%d]", pReqInfo->msgInfo.nAddressCnt);
104
105         for (i = 0; i < pReqInfo->msgInfo.nAddressCnt; i++)
106         {
107                 // Make SMS_SUBMIT_DATA_S from MSG_REQUEST_INFO_S
108                 SMS_SUBMIT_DATA_S submitData = {{0},};
109                 msgInfoToSubmitData(&(pReqInfo->msgInfo), &submitData, &(tpdu.data.submit.dcs.codingScheme), i);
110
111                 // Encode SMSC Address
112                 unsigned char smscAddr[MAX_SMSC_LEN];
113                 memset(smscAddr, 0x00, sizeof(smscAddr));
114
115                 int smscLen = SmsPluginParamCodec::encodeSMSC(&smsc, smscAddr);
116
117                 if (smscLen <= 0) return;
118
119                 for (j = 0; j < smscLen; j++)
120                 {
121                         MSG_DEBUG("pSCAInfo [%02x]", smscAddr[j]);
122                 }
123
124                 int bufLen = 0, reqId = 0;
125
126                 char buf[MAX_TPDU_DATA_LEN];
127
128                 int addLen = strlen(submitData.destAddress.address);
129
130                 tpdu.data.submit.destAddress.ton = submitData.destAddress.ton;
131                 tpdu.data.submit.destAddress.npi = submitData.destAddress.npi;
132
133                 if (addLen < MAX_ADDRESS_LEN) {
134                         memcpy(tpdu.data.submit.destAddress.address, submitData.destAddress.address, addLen);
135                         tpdu.data.submit.destAddress.address[addLen] = '\0';
136                 } else {
137                         memcpy(tpdu.data.submit.destAddress.address, submitData.destAddress.address, MAX_ADDRESS_LEN);
138                         tpdu.data.submit.destAddress.address[MAX_ADDRESS_LEN] = '\0';
139                 }
140
141                 for (unsigned int segCnt = 0; segCnt < submitData.segCount; segCnt++)
142                 {
143                         if (submitData.userData[segCnt].headerCnt > 0)
144                         {
145                                 tpdu.data.submit.bHeaderInd = true;
146                         }
147                         else
148                         {
149                                 tpdu.data.submit.bHeaderInd = false;
150                         }
151
152                         memset(&(tpdu.data.submit.userData), 0x00, sizeof(SMS_USERDATA_S));
153                         memcpy(&(tpdu.data.submit.userData), &(submitData.userData[segCnt]), sizeof(SMS_USERDATA_S));
154
155                         // Encode SMS-SUBMIT TPDU
156                         memset(buf, 0x00, sizeof(buf));
157
158                         bufLen = SmsPluginTpduCodec::encodeTpdu(&tpdu, buf);
159
160                         // Make Telephony Structure
161                         TelSmsDatapackageInfo_t pkgInfo;
162
163                         // Set TPDU data
164                         memset((void*)pkgInfo.szData, 0x00, sizeof(pkgInfo.szData));
165                         memcpy((void*)pkgInfo.szData, buf, bufLen);
166
167                         pkgInfo.szData[bufLen] = 0;
168                         pkgInfo.MsgLength = bufLen;
169
170                         // Set SMSC data
171                         memset(pkgInfo.Sca, 0x00, sizeof(pkgInfo.Sca));
172                         memcpy((void*)pkgInfo.Sca, smscAddr, smscLen);
173                         pkgInfo.Sca[smscLen] = '\0';
174
175                         SMS_SENT_INFO_S sentInfo = {};
176
177                         bool bMoreMsg = FALSE;
178
179                         memcpy(&(sentInfo.reqInfo), pReqInfo, sizeof(SMS_REQUEST_INFO_S));
180
181                         if ((segCnt+1) == submitData.segCount && (i+1)==pReqInfo->msgInfo.nAddressCnt)
182                         {
183                                 sentInfo.bLast = true;
184
185                                 bMoreMsg = FALSE;
186                         }
187                         else
188                         {
189                                 sentInfo.bLast = false;
190
191                                 bMoreMsg = TRUE;
192                         }
193
194                         SmsPluginEventHandler::instance()->SetSentInfo(&sentInfo);
195
196                         curStatus = MSG_NETWORK_SENDING;
197
198                         // Send SMS
199                         int tapiRet = TAPI_API_SUCCESS;
200
201                         tapiRet = tel_send_sms(pTapiHandle, &pkgInfo, bMoreMsg, TapiEventSentStatus, NULL);
202
203                         if (tapiRet == TAPI_API_SUCCESS)
204                         {
205                                 MSG_DEBUG("########  TelTapiSmsSend Success !!! return : [%d] #######", tapiRet);
206                         }
207                         else
208                         {
209                                 SmsPluginEventHandler::instance()->handleSentStatus(MSG_NETWORK_SEND_FAIL);
210
211                                 THROW(MsgException::SMS_PLG_ERROR, "########  TelTapiSmsSend Fail !!! return : [%d] #######", tapiRet);
212                         }
213
214                         // Tizen Validation System
215                         char *msisdn = NULL;
216                         msisdn = MsgSettingGetString(MSG_SIM_MSISDN);
217
218                         MSG_SMS_VLD("[SMS INFO] %d, SMS Send Start, %s->%s, %s",  pReqInfo->msgInfo.msgId, \
219                                                                                                                                                 (msisdn == NULL)?"ME":msisdn, \
220                                                                                                                                                 pReqInfo->msgInfo.addressList[0].addressVal, \
221                                                                                                                                                 (tapiRet == TAPI_API_SUCCESS)?"Success":"Fail");
222
223                         MSG_SMS_VLD("[SMS TEXT] %d, [%s]", pReqInfo->msgInfo.msgId, pReqInfo->msgInfo.msgText);
224
225                         msg_network_status_t retStatus = getNetStatus();
226
227                         MSG_SMS_VLD("[SMS INFO] %d, SMS Send End, %s->%s, %s",  pReqInfo->msgInfo.msgId, \
228                                                                                                                                         (msisdn == NULL)?"ME":msisdn, \
229                                                                                                                                         pReqInfo->msgInfo.addressList[0].addressVal, \
230                                                                                                                                         (retStatus == MSG_NETWORK_SEND_SUCCESS)?"Success":"Fail");
231
232
233                         if (retStatus == MSG_NETWORK_SEND_SUCCESS)
234                         {
235                                 MSG_DEBUG("########  Msg Sent was Successful !!! return : [%d] #######", retStatus);
236                         }
237                         else
238                         {
239                                 MsgInsertTicker("Sending SMS is failed", NULL);
240
241                                 SmsPluginEventHandler::instance()->handleSentStatus(MSG_NETWORK_SEND_FAIL);
242
243                                 THROW(MsgException::SMS_PLG_ERROR, "########  Msg Sent was Failed !!! return : [%d] #######", retStatus);
244                         }
245
246                         if (tpdu.data.submit.userData.headerCnt > 0) tpdu.data.submit.userData.headerCnt--;
247                 }
248         }
249
250         MSG_END();
251 }
252
253
254 void SmsPluginTransport::sendDeliverReport(msg_error_t err)
255 {
256         MSG_BEGIN();
257
258         SMS_TPDU_S tpdu;
259
260         tpdu.tpduType = SMS_TPDU_DELIVER_REP;
261
262         TelSmsResponse_t response;
263
264         int tapiRet = TAPI_API_SUCCESS, reqId = 0;
265
266         if (err == MSG_SUCCESS)
267         {
268                 tpdu.data.deliverRep.reportType = SMS_REPORT_POSITIVE;
269                 response = TAPI_NETTEXT_SENDSMS_SUCCESS;
270
271                 tapiRet = tel_set_sms_memory_status(pTapiHandle, TAPI_NETTEXT_PDA_MEMORY_STATUS_AVAILABLE, TapiEventMemoryStatus, NULL);
272
273                 if (tapiRet == TAPI_API_SUCCESS)
274                 {
275                         MSG_DEBUG("########  tel_set_sms_memory_status() Success !!! req Id : [%d] #######", reqId);
276                 }
277                 else
278                 {
279                         MSG_DEBUG("########  tel_set_sms_memory_status() Failed !!! req Id : [%d] return : [%d] #######", reqId, tapiRet);
280                 }
281         }
282         else if (err == MSG_ERR_SIM_STORAGE_FULL)
283         {
284                 tpdu.data.deliverRep.reportType = SMS_REPORT_NEGATIVE;
285                 tpdu.data.deliverRep.failCause = SMS_FC_MSG_CAPA_EXCEEDED;
286                 response = TAPI_NETTEXT_SIM_FULL;
287
288                 tapiRet = tel_set_sms_memory_status(pTapiHandle, TAPI_NETTEXT_PDA_MEMORY_STATUS_FULL, TapiEventMemoryStatus, NULL);
289
290                 if (tapiRet == TAPI_API_SUCCESS)
291                 {
292                         MSG_DEBUG("########  tel_set_sms_memory_status() Success !!! req Id : [%d] #######", reqId);
293                 }
294                 else
295                 {
296                         MSG_DEBUG("########  tel_set_sms_memory_status() Failed !!! req Id : [%d] return : [%d] #######", reqId, tapiRet);
297                 }
298         }
299         else if (err == MSG_ERR_MESSAGE_COUNT_FULL)
300         {
301                 tpdu.data.deliverRep.reportType = SMS_REPORT_NEGATIVE;
302                 tpdu.data.deliverRep.failCause = SMS_FC_MSG_CAPA_EXCEEDED;
303                 response = TAPI_NETTEXT_ME_FULL;
304
305                 tapiRet = tel_set_sms_memory_status(pTapiHandle, TAPI_NETTEXT_PDA_MEMORY_STATUS_FULL, TapiEventMemoryStatus, NULL);
306
307                 if (tapiRet == TAPI_API_SUCCESS)
308                 {
309                         MSG_DEBUG("########  tel_set_sms_memory_status() Success !!! req Id : [%d] #######", reqId);
310                 }
311                 else
312                 {
313                         MSG_DEBUG("########  tel_set_sms_memory_status() Failed !!! req Id : [%d] return : [%d] #######", reqId, tapiRet);
314                 }
315         }
316         else
317         {
318                 tpdu.data.deliverRep.reportType = SMS_REPORT_NEGATIVE;
319                 tpdu.data.deliverRep.failCause = SMS_FC_UNSPEC_ERROR;
320                 //response = TAPI_NETTEXT_PROTOCOL_ERROR;
321                 // For gcf test [34.2.5.3 class2 message]
322                 response = TAPI_NETTEXT_SIM_FULL;
323
324         }
325
326         MSG_DEBUG("err : [%d], response : [%02x]", err, response);
327
328         tpdu.data.deliverRep.bHeaderInd = false;
329         tpdu.data.deliverRep.paramInd = 0x00;
330
331         // Encode SMS-DELIVER-REPORT TPDU
332         int bufLen = 0;
333
334         char buf[MAX_TPDU_DATA_LEN];
335         memset(buf, 0x00, sizeof(buf));
336
337         bufLen = SmsPluginTpduCodec::encodeTpdu(&tpdu, buf);
338
339         // Make Telephony Structure
340         TelSmsDatapackageInfo_t pkgInfo;
341
342         // Set TPDU data
343         memset((void*)pkgInfo.szData, 0x00, sizeof(pkgInfo.szData));
344         memcpy((void*)pkgInfo.szData, buf, bufLen);
345
346         pkgInfo.szData[bufLen] = 0;
347         pkgInfo.MsgLength = bufLen;
348
349         // Set SMSC Address
350         SMS_ADDRESS_S smsc;
351
352         // Set SMSC Options
353         setSmscOptions(&smsc);
354
355         // Encode SMSC Address
356         unsigned char smscAddr[MAX_SMSC_LEN];
357         memset(smscAddr, 0x00, sizeof(smscAddr));
358
359         int smscLen = SmsPluginParamCodec::encodeSMSC(&smsc, smscAddr);
360
361         if (smscLen <= 0) return;
362
363         // Set SMSC data
364         memset(pkgInfo.Sca, 0x00, sizeof(pkgInfo.Sca));
365         memcpy((void*)pkgInfo.Sca, smscAddr, smscLen);
366         pkgInfo.Sca[smscLen] = '\0';
367
368         // Send Deliver Report
369         tapiRet = tel_send_sms_deliver_report(pTapiHandle, &pkgInfo, response, TapiEventDeliveryReportCNF, NULL);
370
371         if (tapiRet == TAPI_API_SUCCESS)
372         {
373                 MSG_DEBUG("########  tel_send_sms_deliver_report() Success !!! req Id : [%d] #######", reqId);
374         }
375         else
376         {
377                 MSG_DEBUG("########  tel_send_sms_deliver_report() Fail !!! req Id : [%d] return : [%d] #######", reqId, tapiRet);
378         }
379
380         MSG_END();
381 }
382
383
384 void SmsPluginTransport::setSmsSendOptions(SMS_SUBMIT_S *pSubmit)
385 {
386         // Set SMS Send Options
387         pSubmit->bRejectDup = false;
388         pSubmit->bHeaderInd = false;
389
390         MsgSettingGetBool(SMS_SEND_DELIVERY_REPORT, &pSubmit->bStatusReport);
391         MsgSettingGetBool(SMS_SEND_REPLY_PATH, &pSubmit->bReplyPath);
392
393         pSubmit->msgRef = msgRef++;
394
395         pSubmit->dcs.bCompressed = false;
396         pSubmit->dcs.msgClass = SMS_MSG_CLASS_NONE;
397         pSubmit->dcs.codingGroup = SMS_GROUP_GENERAL;
398
399         pSubmit->dcs.codingScheme = (SMS_CODING_SCHEME_T)MsgSettingGetInt(SMS_SEND_DCS);
400
401         MSG_DEBUG("DCS : %d", pSubmit->dcs.codingScheme);
402
403         int selectIdx = MsgSettingGetInt(SMSC_SELECTED);
404
405         char keyName[128];
406
407         memset(keyName, 0x00, sizeof(keyName));
408         sprintf(keyName, "%s/%d", SMSC_PID, selectIdx);
409         MSG_SMS_PID_T pid = (MSG_SMS_PID_T)MsgSettingGetInt(keyName);
410
411         pSubmit->pid = convertPid(pid);
412         MSG_DEBUG("PID : %d", pSubmit->pid);
413
414         memset(keyName, 0x00, sizeof(keyName));
415         sprintf(keyName, "%s/%d", SMSC_VAL_PERIOD, selectIdx);
416         int valPeriod = MsgSettingGetInt(keyName);
417
418         MSG_DEBUG("valPeriod : %d", valPeriod);
419
420         if (valPeriod == 0)
421         {
422                 pSubmit->vpf = SMS_VPF_NOT_PRESENT;
423         }
424         else
425         {
426                 pSubmit->vpf = SMS_VPF_RELATIVE;
427                 pSubmit->validityPeriod.format = SMS_TIME_RELATIVE;
428                 pSubmit->validityPeriod.time.relative.time = valPeriod;
429         }
430 }
431
432
433 void SmsPluginTransport::setSmscOptions(SMS_ADDRESS_S *pSmsc)
434 {
435         // Set SMSC Options
436         int selectIdx = MsgSettingGetInt(SMSC_SELECTED);
437
438         char keyName[128];
439
440         memset(keyName, 0x00, sizeof(keyName));
441         sprintf(keyName, "%s/%d", SMSC_ADDRESS, selectIdx);
442
443         char* tmpValue = NULL;
444
445         tmpValue = MsgSettingGetString(keyName);
446
447         if (tmpValue != NULL)
448         {
449                 memset(pSmsc->address, 0x00, sizeof(pSmsc->address));
450                 strncpy(pSmsc->address, tmpValue, MAX_ADDRESS_LEN);
451
452                 MSG_DEBUG("address : %s", pSmsc->address);
453         }
454         else
455         {
456                 strncpy(pSmsc->address, "+8210911111", MAX_ADDRESS_LEN);
457         }
458
459         memset(keyName, 0x00, sizeof(keyName));
460         sprintf(keyName, "%s/%d", SMSC_TON, selectIdx);
461         pSmsc->ton = (SMS_TON_T)MsgSettingGetInt(keyName);
462
463         MSG_DEBUG("ton : %d", pSmsc->ton);
464
465         memset(keyName, 0x00, sizeof(keyName));
466         sprintf(keyName, "%s/%d", SMSC_NPI, selectIdx);
467         pSmsc->npi = (SMS_NPI_T)MsgSettingGetInt(keyName);
468
469         MSG_DEBUG("npi : %d", pSmsc->npi);
470
471         if (tmpValue != NULL)
472         {
473                 free(tmpValue);
474                 tmpValue = NULL;
475         }
476 }
477
478
479 void SmsPluginTransport::msgInfoToSubmitData(const MSG_MESSAGE_INFO_S *pMsgInfo, SMS_SUBMIT_DATA_S *pData, SMS_CODING_SCHEME_T *pCharType, int addrIndex)
480 {
481         // Destination Address
482         pData->destAddress.ton = SMS_TON_UNKNOWN;
483         pData->destAddress.npi = SMS_NPI_ISDN;
484
485         memset(pData->destAddress.address, 0x00, MAX_ADDRESS_LEN+1);
486         memcpy(pData->destAddress.address, pMsgInfo->addressList[addrIndex].addressVal, MAX_ADDRESS_LEN);
487
488         MSG_DEBUG("ton [%d]", pData->destAddress.ton);
489         MSG_DEBUG("npi [%d]", pData->destAddress.npi);
490         MSG_DEBUG("address [%s]", pData->destAddress.address);
491
492         int decodeLen = 0, bufSize = (MAX_GSM_7BIT_DATA_LEN*MAX_SEGMENT_NUM) + 1;       // SMS_CHARSET_7BIT
493
494         unsigned char decodeData[bufSize];
495         memset(decodeData, 0x00, sizeof(decodeData));
496
497         msg_encode_type_t encodeType = MSG_ENCODE_GSM7BIT;
498
499         MSG_LANGUAGE_ID_T langId = MSG_LANG_ID_RESERVED;
500
501         // User Data
502         if (pMsgInfo->bTextSms == true)
503         {
504                 if (*pCharType == SMS_CHARSET_7BIT)
505                 {
506                         decodeLen = textCvt.convertUTF8ToGSM7bit(decodeData, bufSize, (unsigned char*)pMsgInfo->msgText, pMsgInfo->dataSize, &langId);
507                 }
508                 else if (*pCharType == SMS_CHARSET_8BIT)
509                 {
510                         memcpy(decodeData, pMsgInfo->msgText, pMsgInfo->dataSize);
511                         decodeLen = pMsgInfo->dataSize;
512                 }
513                 else if (*pCharType == SMS_CHARSET_UCS2)
514                 {
515                         decodeLen = textCvt.convertUTF8ToUCS2(decodeData, bufSize, (unsigned char*)pMsgInfo->msgText, pMsgInfo->dataSize);
516                 }
517                 else if (*pCharType == SMS_CHARSET_AUTO)
518                 {
519                         decodeLen = textCvt.convertUTF8ToAuto(decodeData, bufSize, (unsigned char*)pMsgInfo->msgText, pMsgInfo->dataSize, &encodeType);
520                         *pCharType = encodeType;
521                 }
522         }
523         else
524         {
525                 int fileSize = 0;
526
527                 char* pFileData = NULL;
528                 AutoPtr<char> FileBuf(&pFileData);
529
530                 // Read Message Data from File
531                 if (MsgOpenAndReadFile(pMsgInfo->msgData, &pFileData, &fileSize) == false)
532                 THROW(MsgException::FILE_ERROR, "MsgOpenAndReadFile error");
533
534                 MSG_DEBUG("file size : [%d] file data : [%s]", fileSize, pFileData);
535
536                 if (*pCharType == SMS_CHARSET_7BIT)
537                 {
538                         decodeLen = textCvt.convertUTF8ToGSM7bit(decodeData, bufSize, (unsigned char*)pFileData, fileSize, &langId);
539                 }
540                 else if (*pCharType == SMS_CHARSET_8BIT)
541                 {
542                         memcpy(decodeData, pFileData, fileSize);
543                         decodeLen = fileSize;
544                 }
545                 else if (*pCharType == SMS_CHARSET_UCS2)
546                 {
547                         decodeLen = textCvt.convertUTF8ToUCS2(decodeData, bufSize, (unsigned char*)pFileData, fileSize);
548                 }
549                 else if (*pCharType == SMS_CHARSET_AUTO)
550                 {
551                         decodeLen = textCvt.convertUTF8ToAuto(decodeData, bufSize, (unsigned char*)pFileData, fileSize, &encodeType);
552                         *pCharType = encodeType;
553                 }
554
555                 // Delete File
556                 MsgDeleteFile(pMsgInfo->msgData);
557         }
558
559 MSG_DEBUG("decode length : [%d]", decodeLen);
560 MSG_DEBUG("character type : [%d]", *pCharType);
561 MSG_DEBUG("Language Identifier : [%d]", langId);
562 MSG_DEBUG("reply address : [%s]", pMsgInfo->replyAddress);
563
564         int addrLen = 0;
565
566         char* encodedAddr = NULL;
567         AutoPtr<char> addressBuf(&encodedAddr);
568
569         if (strlen(pMsgInfo->replyAddress) > 0)
570         {
571                 SMS_ADDRESS_S replyAddr = {};
572
573                 replyAddr.ton = SMS_TON_NATIONAL;
574                 replyAddr.npi = SMS_NPI_ISDN;
575
576                 memset(replyAddr.address, 0x00, MAX_ADDRESS_LEN+1);
577                 memcpy(replyAddr.address, pMsgInfo->replyAddress, MAX_ADDRESS_LEN);
578
579                 addrLen = SmsPluginParamCodec::encodeAddress(&replyAddr, &encodedAddr);
580
581                 MSG_DEBUG("reply addr length : [%d]", addrLen);
582         }
583
584         int segSize = 0, index = 0;
585
586         segSize = getSegmentSize(*pCharType, decodeLen, pMsgInfo->msgPort.valid, langId, addrLen);
587
588         pData->segCount = ceil((double)decodeLen/(double)segSize);
589
590 MSG_DEBUG("segment size : [%d], pData->segCount : [%d]", segSize, pData->segCount);
591
592         if (pData->segCount > MAX_SEGMENT_NUM)
593                 THROW(MsgException::SMS_PLG_ERROR, "Segment Count is over maximum : %d", pData->segCount);
594
595         int headerCnt = 0;
596
597         for (unsigned int i = 0; i < pData->segCount; i++)
598         {
599                 headerCnt = 0;
600
601                 if ((i + 1) == pData->segCount)
602                         pData->userData[i].length = decodeLen - (i*segSize);
603                 else
604                         pData->userData[i].length = segSize;
605
606                 memset(pData->userData[i].data, 0x00, MAX_USER_DATA_LEN+1);
607                 memcpy(pData->userData[i].data, &(decodeData[index]), pData->userData[i].length);
608                 pData->userData[i].data[pData->userData[i].length] = 0;
609
610 MSG_DEBUG("user data len [%d]", pData->userData[i].length);
611 MSG_DEBUG("user data [%s]", pData->userData[i].data);
612
613                 index += segSize;
614
615                 // Set User Data Header for Concatenated Message
616                 if (pData->segCount > 1)
617                 {
618                         pData->userData[i].header[headerCnt].udhType = SMS_UDH_CONCAT_8BIT;
619                         pData->userData[i].header[headerCnt].udh.concat8bit.msgRef = msgRef8bit;
620                         pData->userData[i].header[headerCnt].udh.concat8bit.totalSeg = pData->segCount;
621                         pData->userData[i].header[headerCnt].udh.concat8bit.seqNum = i + 1;
622
623                         headerCnt++;
624                 }
625
626                 // Set User Data Header Port Information
627                 if (pMsgInfo->msgPort.valid == true)
628                 {
629                         pData->userData[i].header[headerCnt].udhType = SMS_UDH_APP_PORT_16BIT;
630                         pData->userData[i].header[headerCnt].udh.appPort16bit.destPort = pMsgInfo->msgPort.dstPort;
631                         pData->userData[i].header[headerCnt].udh.appPort16bit.originPort = pMsgInfo->msgPort.srcPort;
632
633                         headerCnt++;
634                 }
635
636                 // Set User Data Header for Alternate Reply Address
637                 if (strlen(pMsgInfo->replyAddress) > 0)
638                 {
639                         pData->userData[i].header[headerCnt].udhType = SMS_UDH_ALTERNATE_REPLY_ADDRESS;
640
641                         pData->userData[i].header[headerCnt].udh.alternateAddress.ton = SMS_TON_NATIONAL;
642                         pData->userData[i].header[headerCnt].udh.alternateAddress.npi = SMS_NPI_ISDN;
643
644                         memset(pData->userData[i].header[headerCnt].udh.alternateAddress.address, 0x00, MAX_ADDRESS_LEN+1);
645                         memcpy(pData->userData[i].header[headerCnt].udh.alternateAddress.address, pMsgInfo->replyAddress, MAX_ADDRESS_LEN);
646
647                         headerCnt++;
648                 }
649
650                 // Set User Data Header for National Language Single Shift
651                 if (*pCharType == SMS_CHARSET_7BIT && langId != MSG_LANG_ID_RESERVED)
652                 {
653                         pData->userData[i].header[headerCnt].udhType = SMS_UDH_SINGLE_SHIFT;
654                         pData->userData[i].header[headerCnt].udh.singleShift.langId = langId;
655
656                         headerCnt++;
657                 }
658
659                 pData->userData[i].headerCnt = headerCnt;
660         }
661
662         msgRef8bit++;
663 }
664
665
666 int SmsPluginTransport::getSegmentSize(SMS_CODING_SCHEME_T CodingScheme, int DataLen, bool bPortNum, MSG_LANGUAGE_ID_T LangId, int ReplyAddrLen)
667 {
668         int headerLen = 1, concat = 5, port = 6, lang = 3, reply = 2;
669         int headerSize = 0, segSize = 0, maxSize = 0;
670
671         if (CodingScheme == SMS_CHARSET_7BIT)
672         {
673                 MSG_DEBUG("SMS_CHARSET_7BIT");
674                 maxSize = MAX_GSM_7BIT_DATA_LEN;
675         }
676         else if (CodingScheme == SMS_CHARSET_8BIT || CodingScheme == SMS_CHARSET_UCS2)
677         {
678                 MSG_DEBUG("SMS_CHARSET_8BIT or SMS_CHARSET_UCS2 [%d]", CodingScheme);
679                 maxSize = MAX_UCS2_DATA_LEN;
680         }
681
682         if (bPortNum == true)
683         {
684                 MSG_DEBUG("Port Number Exists");
685                 headerSize += port;
686         }
687
688         if (LangId != MSG_LANG_ID_RESERVED)
689         {
690                 MSG_DEBUG("National Language Exists");
691                 headerSize += lang;
692         }
693
694         if (ReplyAddrLen > 0)
695         {
696                 MSG_DEBUG("Reply Address Exists");
697                 headerSize += reply;
698                 headerSize += ReplyAddrLen;
699         }
700
701         if (CodingScheme == SMS_CHARSET_7BIT)
702         {
703                 if (((DataLen+headerSize)/maxSize) > 1)
704                         segSize = ((140*8) - ((headerLen + concat + headerSize)*8)) / 7;
705                 else
706                         segSize = DataLen;
707         }
708         else if (CodingScheme == SMS_CHARSET_8BIT || CodingScheme == SMS_CHARSET_UCS2)
709         {
710                 if (((DataLen+headerSize)/maxSize) > 1)
711                         segSize = 140 - (headerLen + concat + headerSize);
712                 else
713                         segSize = DataLen;
714         }
715
716         return segSize;
717 }
718
719
720 void SmsPluginTransport::setConcatHeader(SMS_UDH_S *pSrcHeader, SMS_UDH_S *pDstHeader)
721 {
722         pDstHeader->udhType = pSrcHeader->udhType;
723
724         switch (pDstHeader->udhType)
725         {
726                 case SMS_UDH_CONCAT_8BIT :
727                 {
728                         pDstHeader->udh.concat8bit.msgRef = pSrcHeader->udh.concat8bit.msgRef;
729                         pDstHeader->udh.concat8bit.totalSeg = pSrcHeader->udh.concat8bit.totalSeg;
730                         pDstHeader->udh.concat8bit.seqNum = pSrcHeader->udh.concat8bit.seqNum;
731                 }
732                 break;
733
734                 case SMS_UDH_CONCAT_16BIT :
735                 {
736                         pDstHeader->udh.concat16bit.msgRef = pSrcHeader->udh.concat16bit.msgRef;
737                         pDstHeader->udh.concat16bit.totalSeg = pSrcHeader->udh.concat16bit.totalSeg;
738                         pDstHeader->udh.concat16bit.seqNum = pSrcHeader->udh.concat16bit.seqNum;
739                 }
740                 break;
741         }
742 }
743
744
745 void SmsPluginTransport::setNetStatus(msg_network_status_t netStatus)
746 {
747         mx.lock();
748         curStatus = netStatus;
749         cv.signal();
750         mx.unlock();
751 }
752
753
754 msg_network_status_t SmsPluginTransport::getNetStatus()
755 {
756         mx.lock();
757
758         int ret = 0;
759
760         if (curStatus == MSG_NETWORK_SENDING)
761                 ret = cv.timedwait(mx.pMutex(), 65);
762
763         mx.unlock();
764
765         if (ret == ETIMEDOUT)
766         {
767                 MSG_DEBUG("WARNING: SENT STATUS TIME-OUT");
768                 curStatus = MSG_NETWORK_SEND_TIMEOUT;
769         }
770
771         return curStatus;
772 }
773
774
775 unsigned char SmsPluginTransport::getMsgRef()
776 {
777         return msgRef++;
778 }
779
780
781 SMS_PID_T SmsPluginTransport::convertPid(MSG_SMS_PID_T pid)
782 {
783         SMS_PID_T retPid;
784
785         switch (pid)
786         {
787                 case MSG_PID_TEXT :
788                         retPid = SMS_PID_NORMAL;
789                 break;
790                 case MSG_PID_VOICE :
791                         retPid = SMS_PID_VOICE;
792                 break;
793                 case MSG_PID_FAX :
794                         retPid = SMS_PID_TELEX;
795                 break;
796                 case MSG_PID_X400 :
797                         retPid = SMS_PID_x400;
798                 break;
799                 case MSG_PID_ERMES :
800                         retPid = SMS_PID_ERMES;
801                 break;
802                 case MSG_PID_EMAIL :
803                         retPid = SMS_PID_EMAIL;
804                 break;
805                 default :
806                         retPid = SMS_PID_NORMAL;
807                 break;
808         }
809
810         return retPid;
811 }