~ubuntu-branches/ubuntu/trusty/gsmlib/trusty

« back to all changes in this revision

Viewing changes to gsmlib/gsm_sms.cc

  • Committer: Bazaar Package Importer
  • Author(s): Mikael Hedin
  • Date: 2002-01-24 12:59:07 UTC
  • Revision ID: james.westby@ubuntu.com-20020124125907-b7qkpokx5283jdpu
Tags: upstream-1.8
ImportĀ upstreamĀ versionĀ 1.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// *************************************************************************
 
2
// * GSM TA/ME library
 
3
// *
 
4
// * File:    gsm_sms.cc
 
5
// *
 
6
// * Purpose: SMS functions
 
7
// *          (ETSI GSM 07.05)
 
8
// *
 
9
// * Author:  Peter Hofmann (software@pxh.de)
 
10
// *
 
11
// * Created: 16.5.1999
 
12
// *************************************************************************
 
13
 
 
14
#ifdef HAVE_CONFIG_H
 
15
#include <gsm_config.h>
 
16
#endif
 
17
#include <gsmlib/gsm_nls.h>
 
18
#include <gsmlib/gsm_sysdep.h>
 
19
#include <gsmlib/gsm_sms.h>
 
20
#include <gsmlib/gsm_util.h>
 
21
#include <gsmlib/gsm_parser.h>
 
22
#include <gsmlib/gsm_me_ta.h>
 
23
#include <strstream>
 
24
#include <string>
 
25
 
 
26
using namespace std;
 
27
using namespace gsmlib;
 
28
 
 
29
// local constants
 
30
 
 
31
static const string dashes =
 
32
"---------------------------------------------------------------------------";
 
33
 
 
34
// SMSMessage members
 
35
 
 
36
Ref<SMSMessage> SMSMessage::decode(string pdu,
 
37
                                   bool SCtoMEdirection,
 
38
                                   GsmAt *at) throw(GsmException)
 
39
{
 
40
  Ref<SMSMessage> result;
 
41
  SMSDecoder d(pdu);
 
42
  d.getAddress(true);
 
43
  MessageType messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
 
44
  if (SCtoMEdirection)
 
45
    // TPDUs from SC to ME
 
46
    switch (messageTypeIndicator)
 
47
    {
 
48
    case SMS_DELIVER:
 
49
      result = new SMSDeliverMessage(pdu);
 
50
      break;
 
51
 
 
52
    case SMS_STATUS_REPORT:
 
53
      result = new SMSStatusReportMessage(pdu);
 
54
      break;
 
55
 
 
56
    case SMS_SUBMIT_REPORT:
 
57
      // observed with Motorola Timeport 260, the SCtoMEdirection can
 
58
      // be wrong in this case
 
59
      if (at != NULL && at->getMeTa().getCapabilities()._wrongSMSStatusCode)
 
60
        result = new SMSSubmitMessage(pdu);
 
61
      else
 
62
        result = new SMSSubmitReportMessage(pdu);
 
63
      break;
 
64
 
 
65
    default:
 
66
      throw GsmException(_("unhandled SMS TPDU type"), OtherError);
 
67
    }
 
68
  else
 
69
    // TPDUs from ME to SC
 
70
    switch (messageTypeIndicator)
 
71
    {
 
72
    case SMS_SUBMIT:
 
73
      result = new SMSSubmitMessage(pdu);
 
74
      break;
 
75
 
 
76
    case SMS_DELIVER_REPORT:
 
77
      result = new SMSDeliverReportMessage(pdu);
 
78
      break;
 
79
 
 
80
    case SMS_COMMAND:
 
81
      result = new SMSCommandMessage(pdu);
 
82
      break;
 
83
 
 
84
    default:
 
85
      throw GsmException(_("unhandled SMS TPDU type"), OtherError);
 
86
    }
 
87
  result->_at = at;
 
88
  return result;
 
89
}
 
90
 
 
91
Ref<SMSMessage> SMSMessage::decode(istream& s) throw(gsmlib::GsmException)
 
92
{
 
93
  string pdu;
 
94
  unsigned char ScToMe; 
 
95
        
 
96
  s >> ScToMe;
 
97
  s >> pdu;
 
98
 
 
99
  return decode(pdu,ScToMe=='S');
 
100
}
 
101
 
 
102
unsigned char SMSMessage::send(Ref<SMSMessage> &ackPdu)
 
103
  throw(GsmException)
 
104
{
 
105
  if (_messageTypeIndicator != SMS_SUBMIT &&
 
106
      _messageTypeIndicator != SMS_COMMAND)
 
107
    throw GsmException(_("can only send SMS-SUBMIT and SMS-COMMAND TPDUs"),
 
108
                       ParameterError);
 
109
 
 
110
  if (_at.isnull())
 
111
    throw GsmException(_("no device given for sending SMS"), ParameterError);
 
112
 
 
113
  string pdu = encode();
 
114
  Parser p(_at->sendPdu("+CMGS=" +
 
115
                        intToStr(pdu.length() / 2 - getSCAddressLen()),
 
116
                        "+CMGS:", pdu));
 
117
  unsigned char messageReference = p.parseInt();
 
118
 
 
119
  if (p.parseComma(true))
 
120
  {
 
121
    string pdu = p.parseEol();
 
122
 
 
123
    // add missing service centre address if required by ME
 
124
    if (! _at->getMeTa().getCapabilities()._hasSMSSCAprefix)
 
125
      pdu = "00" + pdu;
 
126
 
 
127
    ackPdu = SMSMessage::decode(pdu);
 
128
  }
 
129
  else
 
130
    ackPdu = SMSMessageRef();
 
131
 
 
132
  return messageReference;
 
133
}
 
134
 
 
135
unsigned char SMSMessage::send() throw(GsmException)
 
136
{
 
137
  SMSMessageRef mref;
 
138
  return send(mref);
 
139
}
 
140
 
 
141
unsigned int SMSMessage::getSCAddressLen()
 
142
{
 
143
  SMSEncoder e;
 
144
  e.setAddress(_serviceCentreAddress, true);
 
145
  return e.getLength();
 
146
}
 
147
 
 
148
unsigned char SMSMessage::userDataLength() const
 
149
{
 
150
  unsigned int udhl = _userDataHeader.length();
 
151
  if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
 
152
    return _userData.length() + (udhl ? ((1 + udhl) * 8 + 6) / 7 : 0);
 
153
  else
 
154
    return _userData.length() + (udhl ? (1 + udhl) : 0);
 
155
}
 
156
 
 
157
ostream& SMSMessage::operator<<(ostream& s)
 
158
{
 
159
  unsigned char ScToMe;
 
160
        
 
161
  if (dynamic_cast<SMSDeliverMessage*>(this) || 
 
162
      dynamic_cast<SMSStatusReportMessage*>(this) || 
 
163
      dynamic_cast<SMSSubmitReportMessage*>(this))
 
164
  {
 
165
    ScToMe = 'S';
 
166
  }
 
167
  else if (dynamic_cast<SMSSubmitMessage*>(this) || 
 
168
           dynamic_cast<SMSCommandMessage*>(this) || 
 
169
           dynamic_cast<SMSDeliverReportMessage*>(this))
 
170
  {
 
171
    ScToMe = 'M';
 
172
  }
 
173
  else
 
174
  {
 
175
    throw GsmException(_("unhandled SMS TPDU type"), OtherError);
 
176
  }
 
177
 
 
178
  s << ScToMe;
 
179
  return s << encode();
 
180
}
 
181
 
 
182
// SMSMessage::SMSMessage(SMSMessage &m)
 
183
// {
 
184
//   _at = m._at;
 
185
  
 
186
// }
 
187
 
 
188
// SMSMessage &SMSMessage::operator=(SMSMessage &m)
 
189
// {
 
190
// }
 
191
 
 
192
SMSMessage::~SMSMessage() {}
 
193
 
 
194
// SMSDeliverMessage members
 
195
 
 
196
void SMSDeliverMessage::init()
 
197
{
 
198
  _messageTypeIndicator = SMS_DELIVER;
 
199
  _moreMessagesToSend = false;
 
200
  _replyPath = false;
 
201
  _statusReportIndication = false;
 
202
  _protocolIdentifier = 0;
 
203
}
 
204
 
 
205
SMSDeliverMessage::SMSDeliverMessage()
 
206
{
 
207
  init();
 
208
}
 
209
 
 
210
SMSDeliverMessage::SMSDeliverMessage(string pdu) throw(GsmException)
 
211
{
 
212
  SMSDecoder d(pdu);
 
213
  _serviceCentreAddress = d.getAddress(true);
 
214
  _messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
 
215
  assert(_messageTypeIndicator == SMS_DELIVER);
 
216
  _moreMessagesToSend = d.getBit(); // bit 2
 
217
  d.getBit();                   // bit 3
 
218
  d.getBit();                   // bit 4
 
219
  _statusReportIndication = d.getBit(); // bit 5
 
220
  bool userDataHeaderIndicator = d.getBit(); // bit 6
 
221
  _replyPath = d.getBit();      // bit 7
 
222
  _originatingAddress = d.getAddress();
 
223
  _protocolIdentifier = d.getOctet();
 
224
  _dataCodingScheme = d.getOctet();
 
225
  _serviceCentreTimestamp = d.getTimestamp();
 
226
  unsigned char userDataLength = d.getOctet();
 
227
  d.markSeptet();
 
228
 
 
229
  if (userDataHeaderIndicator)
 
230
  {
 
231
    _userDataHeader.decode(d);
 
232
    if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
 
233
      userDataLength -= ((_userDataHeader.length() + 1) * 8 + 6) / 7;
 
234
    else
 
235
      userDataLength -= ((string)_userDataHeader).length() + 1;
 
236
  }
 
237
  else
 
238
    _userDataHeader = UserDataHeader();
 
239
 
 
240
  if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
 
241
  {                             // userDataLength is length in septets
 
242
    _userData = d.getString(userDataLength);
 
243
    _userData = gsmToLatin1(_userData);
 
244
  }
 
245
  else
 
246
  {                             // userDataLength is length in octets
 
247
    unsigned char *s = 
 
248
      (unsigned char*)alloca(sizeof(unsigned char) * userDataLength);
 
249
    d.getOctets(s, userDataLength);
 
250
    _userData.assign((char*)s, (unsigned int)userDataLength);
 
251
  }
 
252
}
 
253
 
 
254
string SMSDeliverMessage::encode()
 
255
{
 
256
  SMSEncoder e;
 
257
  e.setAddress(_serviceCentreAddress, true);
 
258
  e.set2Bits(_messageTypeIndicator); // bits 0..1
 
259
  e.setBit(_moreMessagesToSend); // bit 2
 
260
  e.setBit();                   // bit 3
 
261
  e.setBit();                   // bit 4
 
262
  e.setBit(_statusReportIndication); // bit 5
 
263
  e.setBit(_userDataHeader.length() != 0); // bit 6
 
264
  e.setBit(_replyPath);         // bit 7
 
265
  e.setAddress(_originatingAddress);
 
266
  e.setOctet(_protocolIdentifier);
 
267
  e.setOctet(_dataCodingScheme);
 
268
  e.setTimestamp(_serviceCentreTimestamp);
 
269
  e.setOctet(userDataLength());
 
270
  e.markSeptet();
 
271
  if (_userDataHeader.length()) _userDataHeader.encode(e);
 
272
  if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
 
273
    e.setString(latin1ToGsm(_userData));
 
274
  else
 
275
    e.setOctets((unsigned char*)_userData.data(), _userData.length());
 
276
  return e.getHexString();
 
277
}
 
278
 
 
279
string SMSDeliverMessage::toString() const
 
280
{
 
281
  ostrstream os;
 
282
  os << dashes << endl
 
283
     << _("Message type: SMS-DELIVER") << endl
 
284
     << _("SC address: '") << _serviceCentreAddress._number << "'" << endl
 
285
     << _("More messages to send: ") << _moreMessagesToSend << endl
 
286
     << _("Reply path: ") << _replyPath << endl
 
287
     << _("User data header indicator: ")
 
288
     << (_userDataHeader.length()!=0) << endl
 
289
     << _("Status report indication: ") << _statusReportIndication << endl
 
290
     << _("Originating address: '") << _originatingAddress._number 
 
291
     << "'" << endl
 
292
     << _("Protocol identifier: 0x") << hex
 
293
     << (unsigned int)_protocolIdentifier << dec << endl
 
294
     << _("Data coding scheme: ") << _dataCodingScheme.toString() << endl
 
295
     << _("SC timestamp: ") << _serviceCentreTimestamp.toString() << endl
 
296
     << _("User data length: ") << (int)userDataLength() << endl
 
297
     << _("User data header: 0x")
 
298
     << bufToHex((unsigned char*)
 
299
                 ((string)_userDataHeader).data(),
 
300
                 ((string)_userDataHeader).length())
 
301
     << endl
 
302
     << _("User data: '") << _userData << "'" << endl
 
303
     << dashes << endl << endl
 
304
     << ends;
 
305
  char *ss = os.str();
 
306
  string result(ss);
 
307
  delete[] ss;
 
308
  return result;
 
309
}
 
310
 
 
311
Address SMSDeliverMessage::address() const
 
312
{
 
313
  return _originatingAddress;
 
314
}
 
315
 
 
316
Ref<SMSMessage> SMSDeliverMessage::clone()
 
317
{
 
318
  Ref<SMSMessage> result = new SMSDeliverMessage(*this);
 
319
  return result;
 
320
}
 
321
 
 
322
// SMSSubmitMessage members
 
323
 
 
324
void SMSSubmitMessage::init()
 
325
{
 
326
  // set everything to sensible default values
 
327
  _messageTypeIndicator = SMS_SUBMIT;
 
328
  _validityPeriodFormat = TimePeriod::Relative; 
 
329
  _validityPeriod._format = TimePeriod::Relative;
 
330
  _validityPeriod._relativeTime = 168; // 2 days
 
331
  _statusReportRequest = false;
 
332
  _replyPath = false;
 
333
  _rejectDuplicates = true;
 
334
  _messageReference = 0;
 
335
  _protocolIdentifier = 0;
 
336
}
 
337
 
 
338
SMSSubmitMessage::SMSSubmitMessage()
 
339
{
 
340
  init();
 
341
}
 
342
 
 
343
SMSSubmitMessage::SMSSubmitMessage(string pdu) throw(GsmException)
 
344
 
345
  SMSDecoder d(pdu);
 
346
  _serviceCentreAddress = d.getAddress(true);
 
347
  _messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
 
348
  assert(_messageTypeIndicator == SMS_SUBMIT);
 
349
  _rejectDuplicates = d.getBit(); // bit 2
 
350
  _validityPeriodFormat = (TimePeriod::Format)d.get2Bits(); // bits 3..4
 
351
  _statusReportRequest = d.getBit(); // bit 5
 
352
  bool userDataHeaderIndicator = d.getBit(); // bit 6
 
353
  _replyPath = d.getBit();      // bit 7
 
354
  _messageReference = d.getOctet();
 
355
  _destinationAddress = d.getAddress();
 
356
  _protocolIdentifier = d.getOctet();
 
357
  _dataCodingScheme = d.getOctet();
 
358
  if (_validityPeriodFormat != TimePeriod::NotPresent)
 
359
    _validityPeriod = d.getTimePeriod(_validityPeriodFormat);
 
360
  unsigned char userDataLength = d.getOctet();
 
361
  d.markSeptet();
 
362
 
 
363
  if (userDataHeaderIndicator)
 
364
  {
 
365
    _userDataHeader.decode(d);
 
366
    if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
 
367
      userDataLength -= ((_userDataHeader.length() + 1) * 8 + 6) / 7;
 
368
    else
 
369
      userDataLength -= ((string)_userDataHeader).length() + 1;
 
370
  }
 
371
  else
 
372
    _userDataHeader = UserDataHeader();
 
373
 
 
374
  if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
 
375
  {                             // userDataLength is length in septets
 
376
    _userData = d.getString(userDataLength);
 
377
    _userData = gsmToLatin1(_userData);
 
378
  }
 
379
  else
 
380
  {                             // _userDataLength is length in octets
 
381
    unsigned char *s =
 
382
      (unsigned char*)alloca(sizeof(unsigned char) * userDataLength);
 
383
    d.getOctets(s, userDataLength);
 
384
    _userData.assign((char*)s, userDataLength);
 
385
  }
 
386
}
 
387
 
 
388
SMSSubmitMessage::SMSSubmitMessage(string text, string number)
 
389
{
 
390
  init();
 
391
  _destinationAddress = Address(number);
 
392
  _userData = text;
 
393
}
 
394
 
 
395
string SMSSubmitMessage::encode()
 
396
{
 
397
  SMSEncoder e;
 
398
  e.setAddress(_serviceCentreAddress, true);
 
399
  e.set2Bits(_messageTypeIndicator); // bits 0..1
 
400
  e.setBit(_rejectDuplicates); // bit 2
 
401
  e.set2Bits(_validityPeriodFormat); // bits 3..4
 
402
  e.setBit(_statusReportRequest); // bit 5
 
403
  bool userDataHeaderIndicator = _userDataHeader.length() != 0;
 
404
  e.setBit(userDataHeaderIndicator); // bit 6
 
405
  e.setBit(_replyPath);       // bit 7
 
406
  e.setOctet(_messageReference);
 
407
  e.setAddress(_destinationAddress);
 
408
  e.setOctet(_protocolIdentifier);
 
409
  e.setOctet(_dataCodingScheme);
 
410
  e.setTimePeriod(_validityPeriod);
 
411
  e.setOctet(userDataLength());
 
412
  e.markSeptet();
 
413
  if (userDataHeaderIndicator) _userDataHeader.encode(e);
 
414
  if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
 
415
    e.setString(latin1ToGsm(_userData));
 
416
  else
 
417
    e.setOctets((unsigned char*)_userData.data(), _userData.length());
 
418
  return e.getHexString();
 
419
}
 
420
 
 
421
string SMSSubmitMessage::toString() const
 
422
{
 
423
  ostrstream os;
 
424
  os << dashes << endl
 
425
     << _("Message type: SMS-SUBMIT") << endl
 
426
     << _("SC address: '") << _serviceCentreAddress._number << "'" << endl
 
427
     << _("Reject duplicates: ") << _rejectDuplicates << endl
 
428
     << _("Validity period format: ");
 
429
  switch (_validityPeriodFormat)
 
430
  {
 
431
  case TimePeriod::NotPresent:
 
432
    os << _("not present");
 
433
    break;
 
434
  case TimePeriod::Relative:
 
435
    os << _("relative");
 
436
    break;
 
437
  case TimePeriod::Absolute:
 
438
    os << _("absolute");
 
439
    break;
 
440
  default:
 
441
    os << _("unknown");
 
442
    break;
 
443
  }
 
444
  os << endl
 
445
     << _("Reply path: ") << _replyPath << endl
 
446
     << _("User data header indicator: ")
 
447
     << (_userDataHeader.length()!=0) << endl
 
448
     << _("Status report request: ") << _statusReportRequest << endl
 
449
     << _("Message reference: ") << (unsigned int)_messageReference << endl
 
450
     << _("Destination address: '") << _destinationAddress._number 
 
451
     << "'" << endl
 
452
     << _("Protocol identifier: 0x") << hex 
 
453
     << (unsigned int)_protocolIdentifier << dec << endl
 
454
     << _("Data coding scheme: ") << _dataCodingScheme.toString() << endl
 
455
     << _("Validity period: ") << _validityPeriod.toString() << endl
 
456
     << _("User data length: ") << (int)userDataLength() << endl
 
457
     << _("User data header: 0x") << bufToHex((unsigned char*)
 
458
                                              ((string)_userDataHeader).data(),
 
459
                                              _userDataHeader.length())
 
460
     << endl
 
461
     << _("User data: '") << _userData << "'" << endl
 
462
     << dashes << endl << endl
 
463
     << ends;
 
464
  char *ss = os.str();
 
465
  string result(ss);
 
466
  delete[] ss;
 
467
  return result; 
 
468
}
 
469
 
 
470
Address SMSSubmitMessage::address() const
 
471
{
 
472
  return _destinationAddress;
 
473
}
 
474
 
 
475
Ref<SMSMessage> SMSSubmitMessage::clone()
 
476
{
 
477
  Ref<SMSMessage> result = new SMSSubmitMessage(*this);
 
478
  return result;
 
479
}
 
480
 
 
481
// SMSStatusReportMessage members
 
482
 
 
483
void SMSStatusReportMessage::init()
 
484
{
 
485
  _messageTypeIndicator = SMS_STATUS_REPORT;
 
486
  _moreMessagesToSend = false;
 
487
  _statusReportQualifier = false;
 
488
  _messageReference = 0;
 
489
  _status = SMS_STATUS_RECEIVED;
 
490
}
 
491
 
 
492
SMSStatusReportMessage::SMSStatusReportMessage(string pdu) throw(GsmException)
 
493
{
 
494
  SMSDecoder d(pdu);
 
495
  _serviceCentreAddress = d.getAddress(true);
 
496
  _messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
 
497
  assert(_messageTypeIndicator == SMS_STATUS_REPORT);
 
498
  _moreMessagesToSend = d.getBit(); // bit 2
 
499
  d.getBit();                   // bit 3
 
500
  d.getBit();                   // bit 4
 
501
  _statusReportQualifier = d.getBit(); // bit 5
 
502
  _messageReference = d.getOctet();
 
503
  _recipientAddress = d.getAddress();
 
504
  _serviceCentreTimestamp = d.getTimestamp();
 
505
  _dischargeTime = d.getTimestamp();
 
506
  _status = d.getOctet();
 
507
}
 
508
 
 
509
string SMSStatusReportMessage::encode()
 
510
{
 
511
  SMSEncoder e;
 
512
  e.setAddress(_serviceCentreAddress, true);
 
513
  e.set2Bits(_messageTypeIndicator); // bits 0..1
 
514
  e.setBit(_moreMessagesToSend); // bit 2
 
515
  e.setBit();                   // bit 3
 
516
  e.setBit();                   // bit 4
 
517
  e.setBit(_statusReportQualifier); // bit 5
 
518
  e.setOctet(_messageReference);
 
519
  e.setAddress(_recipientAddress);
 
520
  e.setTimestamp(_serviceCentreTimestamp);
 
521
  e.setTimestamp(_dischargeTime);
 
522
  e.setOctet(_status);
 
523
  return e.getHexString();
 
524
}
 
525
 
 
526
string SMSStatusReportMessage::toString() const
 
527
{
 
528
  ostrstream os;
 
529
  os << dashes << endl
 
530
     << _("Message type: SMS-STATUS-REPORT") << endl
 
531
     << _("SC address: '") << _serviceCentreAddress._number << "'" << endl
 
532
     << _("More messages to send: ") << _moreMessagesToSend << endl
 
533
     << _("Status report qualifier: ") << _statusReportQualifier << endl
 
534
     << _("Message reference: ") << (unsigned int)_messageReference << endl
 
535
     << _("Recipient address: '") << _recipientAddress._number << "'" << endl
 
536
     << _("SC timestamp: ") << _serviceCentreTimestamp.toString() << endl
 
537
     << _("Discharge time: ") << _dischargeTime.toString() << endl
 
538
     << _("Status: 0x") << hex << (unsigned int)_status << dec
 
539
     << " '" << getSMSStatusString(_status) << "'" << endl
 
540
     << dashes << endl << endl
 
541
     << ends;
 
542
  char *ss = os.str();
 
543
  string result(ss);
 
544
  delete[] ss;
 
545
  return result; 
 
546
}
 
547
 
 
548
Address SMSStatusReportMessage::address() const
 
549
{
 
550
  return _recipientAddress;
 
551
}
 
552
 
 
553
Ref<SMSMessage> SMSStatusReportMessage::clone()
 
554
{
 
555
  Ref<SMSMessage> result = new SMSStatusReportMessage(*this);
 
556
  return result;
 
557
}
 
558
 
 
559
// SMSCommandMessage members
 
560
 
 
561
void SMSCommandMessage::init()
 
562
{
 
563
  _messageTypeIndicator = SMS_COMMAND;
 
564
  _messageReference = 0;
 
565
  _statusReportRequest = true;
 
566
  _protocolIdentifier = 0;
 
567
  _commandType = EnquireSM;
 
568
  _messageNumber = 0;
 
569
  _commandDataLength = 0; 
 
570
}
 
571
 
 
572
SMSCommandMessage::SMSCommandMessage(string pdu) throw(GsmException)
 
573
{
 
574
  SMSDecoder d(pdu);
 
575
  _serviceCentreAddress = d.getAddress(true);
 
576
  _messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
 
577
  assert(_messageTypeIndicator == SMS_COMMAND);
 
578
  d.getBit();                   // bit 2
 
579
  d.getBit();                   // bit 3
 
580
  d.getBit();                   // bit 4
 
581
  _statusReportRequest = d.getBit(); // bit 5
 
582
  _messageReference = d.getOctet();
 
583
  _protocolIdentifier = d.getOctet();
 
584
  _commandType = d.getOctet();
 
585
  _messageNumber = d.getOctet();
 
586
  _destinationAddress = d.getAddress();
 
587
  _commandDataLength = d.getOctet();
 
588
  unsigned char *s = 
 
589
      (unsigned char*)alloca(sizeof(unsigned char) * _commandDataLength);
 
590
  d.getOctets(s, _commandDataLength);
 
591
}
 
592
 
 
593
string SMSCommandMessage::encode()
 
594
{
 
595
  SMSEncoder e;
 
596
  e.setAddress(_serviceCentreAddress, true);
 
597
  e.set2Bits(_messageTypeIndicator); // bits 0..1
 
598
  e.setBit();                   // bit 2
 
599
  e.setBit();                   // bit 3
 
600
  e.setBit();                   // bit 4
 
601
  e.setBit(_statusReportRequest); // bit 5
 
602
  e.setOctet(_messageReference);
 
603
  e.setOctet(_protocolIdentifier);
 
604
  e.setOctet(_commandType);
 
605
  e.setOctet(_messageNumber);
 
606
  e.setAddress(_destinationAddress);
 
607
  e.setOctet(_commandData.length());
 
608
  e.setOctets((const unsigned char*)_commandData.data(),
 
609
              (short unsigned int)_commandData.length());
 
610
  return e.getHexString();
 
611
}
 
612
 
 
613
string SMSCommandMessage::toString() const
 
614
{
 
615
  ostrstream os;
 
616
  os << dashes << endl
 
617
     << _("Message type: SMS-COMMAND") << endl
 
618
     << _("SC address: '") << _serviceCentreAddress._number << "'" << endl
 
619
     << _("Message reference: ") << (unsigned int)_messageReference << endl
 
620
     << _("Status report request: ") << _statusReportRequest << endl
 
621
     << _("Protocol identifier: 0x") << hex 
 
622
     << (unsigned int)_protocolIdentifier << dec << endl
 
623
     << _("Command type: 0x") << hex << (unsigned int)_commandType
 
624
     << dec << endl
 
625
     << _("Message number: ") << (unsigned int)_messageNumber << endl
 
626
     << _("Destination address: '") << _destinationAddress._number 
 
627
     << "'" << endl
 
628
     << _("Command data length: ") << (unsigned int)_commandDataLength << endl
 
629
     << _("Command data: '") << _commandData << "'" << endl
 
630
     << dashes << endl << endl
 
631
     << ends;
 
632
  char *ss = os.str();
 
633
  string result(ss);
 
634
  delete[] ss;
 
635
  return result; 
 
636
}
 
637
 
 
638
Address SMSCommandMessage::address() const
 
639
{
 
640
  return _destinationAddress;
 
641
}
 
642
 
 
643
Ref<SMSMessage> SMSCommandMessage::clone()
 
644
{
 
645
  Ref<SMSMessage> result = new SMSCommandMessage(*this);
 
646
  return result;
 
647
}
 
648
 
 
649
// SMSDeliverReportMessage members
 
650
 
 
651
void SMSDeliverReportMessage::init()
 
652
{
 
653
  _messageTypeIndicator = SMS_DELIVER_REPORT;
 
654
  _protocolIdentifierPresent = false;
 
655
  _dataCodingSchemePresent = false;
 
656
  _userDataLengthPresent = false;
 
657
}
 
658
 
 
659
SMSDeliverReportMessage::SMSDeliverReportMessage(string pdu)
 
660
  throw(GsmException)
 
661
{
 
662
  SMSDecoder d(pdu);
 
663
  _serviceCentreAddress = d.getAddress(true);
 
664
  _messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
 
665
  assert(_messageTypeIndicator == SMS_DELIVER_REPORT);
 
666
  d.alignOctet();               // skip to parameter indicator
 
667
  _protocolIdentifierPresent = d.getBit(); // bit 0
 
668
  _dataCodingSchemePresent = d.getBit(); // bit 1
 
669
  _userDataLengthPresent = d.getBit(); // bit 2
 
670
  if (_protocolIdentifierPresent)
 
671
    _protocolIdentifier = d.getOctet();
 
672
  if (_dataCodingSchemePresent)
 
673
    _dataCodingScheme = d.getOctet();
 
674
  if (_userDataLengthPresent)
 
675
  {
 
676
    unsigned char userDataLength = d.getOctet();
 
677
    d.markSeptet();
 
678
    if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
 
679
    {
 
680
      _userData = d.getString(userDataLength);
 
681
      _userData = gsmToLatin1(_userData);
 
682
    }
 
683
    else
 
684
    {                           // userDataLength is length in octets
 
685
      unsigned char *s =
 
686
        (unsigned char*)alloca(sizeof(unsigned char) * userDataLength);
 
687
      d.getOctets(s, userDataLength);
 
688
      _userData.assign((char*)s, userDataLength);
 
689
    }
 
690
  }
 
691
}
 
692
 
 
693
string SMSDeliverReportMessage::encode()
 
694
{
 
695
  SMSEncoder e;
 
696
  e.setAddress(_serviceCentreAddress, true);
 
697
  e.set2Bits(_messageTypeIndicator); // bits 0..1
 
698
  e.alignOctet();               // skip to parameter indicator
 
699
  e.setBit(_protocolIdentifierPresent); // bit 0
 
700
  e.setBit(_dataCodingSchemePresent); // bit 1
 
701
  e.setBit(_userDataLengthPresent); // bit 2
 
702
  if (_protocolIdentifierPresent)
 
703
    e.setOctet(_protocolIdentifier);
 
704
  if (_dataCodingSchemePresent)
 
705
    e.setOctet(_dataCodingScheme);
 
706
  if (_userDataLengthPresent)
 
707
  {
 
708
    unsigned char userDataLength = _userData.length();
 
709
    e.setOctet(userDataLength);
 
710
    if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
 
711
      e.setString(latin1ToGsm(_userData));
 
712
    else
 
713
      e.setOctets((unsigned char*)_userData.data(), userDataLength);
 
714
  }
 
715
  return e.getHexString();
 
716
}
 
717
 
 
718
string SMSDeliverReportMessage::toString() const
 
719
{
 
720
  ostrstream os;
 
721
  os << dashes << endl
 
722
     << _("Message type: SMS-DELIVER-REPORT") << endl
 
723
     << _("SC address: '") << _serviceCentreAddress._number << "'" << endl
 
724
     << _("Protocol identifier present: ") << _protocolIdentifierPresent
 
725
     << endl
 
726
     << _("Data coding scheme present: ") << _dataCodingSchemePresent << endl
 
727
     << _("User data length present: ") << _userDataLengthPresent << endl;
 
728
  if (_protocolIdentifierPresent)
 
729
    os << _("Protocol identifier: 0x") << hex
 
730
       << (unsigned int)_protocolIdentifier
 
731
       << dec << endl;
 
732
  if (_dataCodingSchemePresent)
 
733
    os << _("Data coding scheme: ") << _dataCodingScheme.toString() << endl;
 
734
  if (_userDataLengthPresent)
 
735
    os << _("User data length: ") << (int)userDataLength() << endl
 
736
       << _("User data: '") << _userData << "'" << endl;
 
737
  os << dashes << endl << endl
 
738
     << ends;
 
739
  char *ss = os.str();
 
740
  string result(ss);
 
741
  delete[] ss;
 
742
  return result; 
 
743
}
 
744
 
 
745
Address SMSDeliverReportMessage::address() const
 
746
{
 
747
  assert(0);                    // not address, should not be in SMS store
 
748
  return Address();
 
749
}
 
750
 
 
751
Ref<SMSMessage> SMSDeliverReportMessage::clone()
 
752
{
 
753
  Ref<SMSMessage> result = new SMSDeliverReportMessage(*this);
 
754
  return result;
 
755
}
 
756
 
 
757
// SMSSubmitReportMessage members
 
758
 
 
759
void SMSSubmitReportMessage::init()
 
760
{
 
761
  _messageTypeIndicator = SMS_SUBMIT_REPORT;
 
762
  _protocolIdentifierPresent = false;
 
763
  _dataCodingSchemePresent = false;
 
764
  _userDataLengthPresent = false;
 
765
}
 
766
 
 
767
SMSSubmitReportMessage::SMSSubmitReportMessage(string pdu) throw(GsmException)
 
768
{
 
769
  SMSDecoder d(pdu);
 
770
  _serviceCentreAddress = d.getAddress(true);
 
771
  _messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
 
772
  assert(_messageTypeIndicator == SMS_SUBMIT_REPORT);
 
773
  _serviceCentreTimestamp = d.getTimestamp();
 
774
  _protocolIdentifierPresent = d.getBit(); // bit 0
 
775
  _dataCodingSchemePresent = d.getBit(); // bit 1
 
776
  _userDataLengthPresent = d.getBit(); // bit 2
 
777
  if (_protocolIdentifierPresent)
 
778
    _protocolIdentifier = d.getOctet();
 
779
  if (_dataCodingSchemePresent)
 
780
    _dataCodingScheme = d.getOctet();
 
781
  if (_userDataLengthPresent)
 
782
  {
 
783
    unsigned char userDataLength = d.getOctet();
 
784
    d.markSeptet();
 
785
    if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
 
786
    {
 
787
      _userData = d.getString(userDataLength);
 
788
      _userData = gsmToLatin1(_userData);
 
789
    }
 
790
    else
 
791
    {                           // _userDataLength is length in octets
 
792
      unsigned char *s =
 
793
        (unsigned char*)alloca(sizeof(unsigned char) * userDataLength);
 
794
      d.getOctets(s, userDataLength);
 
795
      _userData.assign((char*)s, userDataLength);
 
796
    }
 
797
  }
 
798
}
 
799
 
 
800
string SMSSubmitReportMessage::encode()
 
801
{
 
802
  SMSEncoder e;
 
803
  e.setAddress(_serviceCentreAddress, true);
 
804
  e.set2Bits(_messageTypeIndicator); // bits 0..1
 
805
  e.setTimestamp(_serviceCentreTimestamp);
 
806
  e.setBit(_protocolIdentifierPresent); // bit 0
 
807
  e.setBit(_dataCodingSchemePresent); // bit 1
 
808
  e.setBit(_userDataLengthPresent); // bit 2
 
809
  if (_protocolIdentifierPresent)
 
810
    e.setOctet(_protocolIdentifier);
 
811
  if (_dataCodingSchemePresent)
 
812
    e.setOctet(_dataCodingScheme);
 
813
  if (_userDataLengthPresent)
 
814
  {
 
815
    e.setOctet(userDataLength());
 
816
    if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
 
817
      e.setString(latin1ToGsm(_userData));
 
818
    else
 
819
      e.setOctets((unsigned char*)_userData.data(), _userData.length());
 
820
  }
 
821
  return e.getHexString();
 
822
}
 
823
 
 
824
string SMSSubmitReportMessage::toString() const
 
825
{
 
826
  ostrstream os;
 
827
  os << dashes << endl
 
828
     << _("Message type: SMS-SUBMIT-REPORT") << endl
 
829
     << _("SC address: '") << _serviceCentreAddress._number << "'" << endl
 
830
     << _("SC timestamp: ") << _serviceCentreTimestamp.toString() << endl
 
831
     << _("Protocol identifier present: ") << _protocolIdentifierPresent
 
832
     << endl
 
833
     << _("Data coding scheme present: ") << _dataCodingSchemePresent << endl
 
834
     << _("User data length present: ") << _userDataLengthPresent << endl;
 
835
  if (_protocolIdentifierPresent)
 
836
    os << _("Protocol identifier: 0x") << hex
 
837
       << (unsigned int)_protocolIdentifier
 
838
       << dec << endl;
 
839
  if (_dataCodingSchemePresent)
 
840
    os << _("Data coding scheme: ") << _dataCodingScheme.toString() << endl;
 
841
  if (_userDataLengthPresent)
 
842
    os << _("User data length: ") << (int)userDataLength() << endl
 
843
       << _("User data: '") << _userData << "'" << endl;
 
844
  os << dashes << endl << endl
 
845
     << ends;
 
846
  char *ss = os.str();
 
847
  string result(ss);
 
848
  delete[] ss;
 
849
  return result; 
 
850
}
 
851
 
 
852
Address SMSSubmitReportMessage::address() const
 
853
{
 
854
  assert(0);                    // not address, should not be in SMS store
 
855
  return Address();
 
856
}
 
857
 
 
858
Ref<SMSMessage> SMSSubmitReportMessage::clone()
 
859
{
 
860
  Ref<SMSMessage> result = new SMSSubmitReportMessage(*this);
 
861
  return result;
 
862
}
 
863