?? gsm_sms.c
字號:
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_sms.cc
// *
// * Purpose: SMS functions
// * (ETSI GSM 07.05)
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 16.5.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_nls.h>
#include <gsmlib/gsm_sysdep.h>
#include <gsmlib/gsm_sms.h>
#include <gsmlib/gsm_util.h>
#include <gsmlib/gsm_parser.h>
#include <gsmlib/gsm_me_ta.h>
#include <strstream>
#include <string>
using namespace std;
using namespace gsmlib;
// local constants
static const string dashes =
"---------------------------------------------------------------------------";
// SMSMessage members
Ref<SMSMessage> SMSMessage::decode(string pdu,
bool SCtoMEdirection,
GsmAt *at) throw(GsmException)
{
Ref<SMSMessage> result;
SMSDecoder d(pdu);
d.getAddress(true);
MessageType messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
if (SCtoMEdirection)
// TPDUs from SC to ME
switch (messageTypeIndicator)
{
case SMS_DELIVER:
result = new SMSDeliverMessage(pdu);
break;
case SMS_STATUS_REPORT:
result = new SMSStatusReportMessage(pdu);
break;
case SMS_SUBMIT_REPORT:
// observed with Motorola Timeport 260, the SCtoMEdirection can
// be wrong in this case
if (at != NULL && at->getMeTa().getCapabilities()._wrongSMSStatusCode)
result = new SMSSubmitMessage(pdu);
else
result = new SMSSubmitReportMessage(pdu);
break;
default:
throw GsmException(_("unhandled SMS TPDU type"), OtherError);
}
else
// TPDUs from ME to SC
switch (messageTypeIndicator)
{
case SMS_SUBMIT:
result = new SMSSubmitMessage(pdu);
break;
case SMS_DELIVER_REPORT:
result = new SMSDeliverReportMessage(pdu);
break;
case SMS_COMMAND:
result = new SMSCommandMessage(pdu);
break;
default:
throw GsmException(_("unhandled SMS TPDU type"), OtherError);
}
result->_at = at;
return result;
}
Ref<SMSMessage> SMSMessage::decode(istream& s) throw(gsmlib::GsmException)
{
string pdu;
unsigned char ScToMe;
s >> ScToMe;
s >> pdu;
return decode(pdu,ScToMe=='S');
}
unsigned char SMSMessage::send(Ref<SMSMessage> &ackPdu)
throw(GsmException)
{
if (_messageTypeIndicator != SMS_SUBMIT &&
_messageTypeIndicator != SMS_COMMAND)
throw GsmException(_("can only send SMS-SUBMIT and SMS-COMMAND TPDUs"),
ParameterError);
if (_at.isnull())
throw GsmException(_("no device given for sending SMS"), ParameterError);
string pdu = encode();
Parser p(_at->sendPdu("+CMGS=" +
intToStr(pdu.length() / 2 - getSCAddressLen()),
"+CMGS:", pdu));
unsigned char messageReference = p.parseInt();
if (p.parseComma(true))
{
string pdu = p.parseEol();
// add missing service centre address if required by ME
if (! _at->getMeTa().getCapabilities()._hasSMSSCAprefix)
pdu = "00" + pdu;
ackPdu = SMSMessage::decode(pdu);
}
else
ackPdu = SMSMessageRef();
return messageReference;
}
unsigned char SMSMessage::send() throw(GsmException)
{
SMSMessageRef mref;
return send(mref);
}
unsigned int SMSMessage::getSCAddressLen()
{
SMSEncoder e;
e.setAddress(_serviceCentreAddress, true);
return e.getLength();
}
unsigned char SMSMessage::userDataLength() const
{
unsigned int udhl = _userDataHeader.length();
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
return _userData.length() + (udhl ? ((1 + udhl) * 8 + 6) / 7 : 0);
else
return _userData.length() + (udhl ? (1 + udhl) : 0);
}
ostream& SMSMessage::operator<<(ostream& s)
{
unsigned char ScToMe;
if (dynamic_cast<SMSDeliverMessage*>(this) ||
dynamic_cast<SMSStatusReportMessage*>(this) ||
dynamic_cast<SMSSubmitReportMessage*>(this))
{
ScToMe = 'S';
}
else if (dynamic_cast<SMSSubmitMessage*>(this) ||
dynamic_cast<SMSCommandMessage*>(this) ||
dynamic_cast<SMSDeliverReportMessage*>(this))
{
ScToMe = 'M';
}
else
{
throw GsmException(_("unhandled SMS TPDU type"), OtherError);
}
s << ScToMe;
return s << encode();
}
// SMSMessage::SMSMessage(SMSMessage &m)
// {
// _at = m._at;
// }
// SMSMessage &SMSMessage::operator=(SMSMessage &m)
// {
// }
SMSMessage::~SMSMessage() {}
// SMSDeliverMessage members
void SMSDeliverMessage::init()
{
_messageTypeIndicator = SMS_DELIVER;
_moreMessagesToSend = false;
_replyPath = false;
_statusReportIndication = false;
_protocolIdentifier = 0;
}
SMSDeliverMessage::SMSDeliverMessage()
{
init();
}
SMSDeliverMessage::SMSDeliverMessage(string pdu) throw(GsmException)
{
SMSDecoder d(pdu);
_serviceCentreAddress = d.getAddress(true);
_messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
assert(_messageTypeIndicator == SMS_DELIVER);
_moreMessagesToSend = d.getBit(); // bit 2
d.getBit(); // bit 3
d.getBit(); // bit 4
_statusReportIndication = d.getBit(); // bit 5
bool userDataHeaderIndicator = d.getBit(); // bit 6
_replyPath = d.getBit(); // bit 7
_originatingAddress = d.getAddress();
_protocolIdentifier = d.getOctet();
_dataCodingScheme = d.getOctet();
_serviceCentreTimestamp = d.getTimestamp();
unsigned char userDataLength = d.getOctet();
d.markSeptet();
if (userDataHeaderIndicator)
{
_userDataHeader.decode(d);
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
userDataLength -= ((_userDataHeader.length() + 1) * 8 + 6) / 7;
else
userDataLength -= ((string)_userDataHeader).length() + 1;
}
else
_userDataHeader = UserDataHeader();
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
{ // userDataLength is length in septets
_userData = d.getString(userDataLength);
_userData = gsmToLatin1(_userData);
}
else
{ // userDataLength is length in octets
unsigned char *s =
(unsigned char*)alloca(sizeof(unsigned char) * userDataLength);
d.getOctets(s, userDataLength);
_userData.assign((char*)s, (unsigned int)userDataLength);
}
}
string SMSDeliverMessage::encode()
{
SMSEncoder e;
e.setAddress(_serviceCentreAddress, true);
e.set2Bits(_messageTypeIndicator); // bits 0..1
e.setBit(_moreMessagesToSend); // bit 2
e.setBit(); // bit 3
e.setBit(); // bit 4
e.setBit(_statusReportIndication); // bit 5
e.setBit(_userDataHeader.length() != 0); // bit 6
e.setBit(_replyPath); // bit 7
e.setAddress(_originatingAddress);
e.setOctet(_protocolIdentifier);
e.setOctet(_dataCodingScheme);
e.setTimestamp(_serviceCentreTimestamp);
e.setOctet(userDataLength());
e.markSeptet();
if (_userDataHeader.length()) _userDataHeader.encode(e);
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
e.setString(latin1ToGsm(_userData));
else
e.setOctets((unsigned char*)_userData.data(), _userData.length());
return e.getHexString();
}
string SMSDeliverMessage::toString() const
{
ostrstream os;
os << dashes << endl
<< _("Message type: SMS-DELIVER") << endl
<< _("SC address: '") << _serviceCentreAddress._number << "'" << endl
<< _("More messages to send: ") << _moreMessagesToSend << endl
<< _("Reply path: ") << _replyPath << endl
<< _("User data header indicator: ")
<< (_userDataHeader.length()!=0) << endl
<< _("Status report indication: ") << _statusReportIndication << endl
<< _("Originating address: '") << _originatingAddress._number
<< "'" << endl
<< _("Protocol identifier: 0x") << hex
<< (unsigned int)_protocolIdentifier << dec << endl
<< _("Data coding scheme: ") << _dataCodingScheme.toString() << endl
<< _("SC timestamp: ") << _serviceCentreTimestamp.toString() << endl
<< _("User data length: ") << (int)userDataLength() << endl
<< _("User data header: 0x")
<< bufToHex((unsigned char*)
((string)_userDataHeader).data(),
((string)_userDataHeader).length())
<< endl
<< _("User data: '") << _userData << "'" << endl
<< dashes << endl << endl
<< ends;
char *ss = os.str();
string result(ss);
delete[] ss;
return result;
}
Address SMSDeliverMessage::address() const
{
return _originatingAddress;
}
Ref<SMSMessage> SMSDeliverMessage::clone()
{
Ref<SMSMessage> result = new SMSDeliverMessage(*this);
return result;
}
// SMSSubmitMessage members
void SMSSubmitMessage::init()
{
// set everything to sensible default values
_messageTypeIndicator = SMS_SUBMIT;
_validityPeriodFormat = TimePeriod::Relative;
_validityPeriod._format = TimePeriod::Relative;
_validityPeriod._relativeTime = 168; // 2 days
_statusReportRequest = false;
_replyPath = false;
_rejectDuplicates = true;
_messageReference = 0;
_protocolIdentifier = 0;
}
SMSSubmitMessage::SMSSubmitMessage()
{
init();
}
SMSSubmitMessage::SMSSubmitMessage(string pdu) throw(GsmException)
{
SMSDecoder d(pdu);
_serviceCentreAddress = d.getAddress(true);
_messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
assert(_messageTypeIndicator == SMS_SUBMIT);
_rejectDuplicates = d.getBit(); // bit 2
_validityPeriodFormat = (TimePeriod::Format)d.get2Bits(); // bits 3..4
_statusReportRequest = d.getBit(); // bit 5
bool userDataHeaderIndicator = d.getBit(); // bit 6
_replyPath = d.getBit(); // bit 7
_messageReference = d.getOctet();
_destinationAddress = d.getAddress();
_protocolIdentifier = d.getOctet();
_dataCodingScheme = d.getOctet();
if (_validityPeriodFormat != TimePeriod::NotPresent)
_validityPeriod = d.getTimePeriod(_validityPeriodFormat);
unsigned char userDataLength = d.getOctet();
d.markSeptet();
if (userDataHeaderIndicator)
{
_userDataHeader.decode(d);
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
userDataLength -= ((_userDataHeader.length() + 1) * 8 + 6) / 7;
else
userDataLength -= ((string)_userDataHeader).length() + 1;
}
else
_userDataHeader = UserDataHeader();
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
{ // userDataLength is length in septets
_userData = d.getString(userDataLength);
_userData = gsmToLatin1(_userData);
}
else
{ // _userDataLength is length in octets
unsigned char *s =
(unsigned char*)alloca(sizeof(unsigned char) * userDataLength);
d.getOctets(s, userDataLength);
_userData.assign((char*)s, userDataLength);
}
}
SMSSubmitMessage::SMSSubmitMessage(string text, string number)
{
init();
_destinationAddress = Address(number);
_userData = text;
}
string SMSSubmitMessage::encode()
{
SMSEncoder e;
e.setAddress(_serviceCentreAddress, true);
e.set2Bits(_messageTypeIndicator); // bits 0..1
e.setBit(_rejectDuplicates); // bit 2
e.set2Bits(_validityPeriodFormat); // bits 3..4
e.setBit(_statusReportRequest); // bit 5
bool userDataHeaderIndicator = _userDataHeader.length() != 0;
e.setBit(userDataHeaderIndicator); // bit 6
e.setBit(_replyPath); // bit 7
e.setOctet(_messageReference);
e.setAddress(_destinationAddress);
e.setOctet(_protocolIdentifier);
e.setOctet(_dataCodingScheme);
e.setTimePeriod(_validityPeriod);
e.setOctet(userDataLength());
e.markSeptet();
if (userDataHeaderIndicator) _userDataHeader.encode(e);
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
e.setString(latin1ToGsm(_userData));
else
e.setOctets((unsigned char*)_userData.data(), _userData.length());
return e.getHexString();
}
string SMSSubmitMessage::toString() const
{
ostrstream os;
os << dashes << endl
<< _("Message type: SMS-SUBMIT") << endl
<< _("SC address: '") << _serviceCentreAddress._number << "'" << endl
<< _("Reject duplicates: ") << _rejectDuplicates << endl
<< _("Validity period format: ");
switch (_validityPeriodFormat)
{
case TimePeriod::NotPresent:
os << _("not present");
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -