/[projects]/smsdaemon/SmsPdu.cpp
ViewVC logotype

Contents of /smsdaemon/SmsPdu.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 68 - (show annotations) (download)
Thu Jun 12 18:54:24 2008 UTC (15 years, 11 months ago) by torben
File size: 4074 byte(s)
Added pdu decode helper functions.

1 /* using http://sourceforge.net/projects/libserial/
2 */
3
4
5 #include "SmsPdu.h"
6
7 #include <string>
8 #include <sstream>
9
10 #include <time.h>
11 #include <stdlib.h>
12
13 #include "common.h"
14 #include "util.h"
15
16
17 using namespace std;
18
19
20 namespace SmsPdu
21 {
22
23
24
25 string SwitchChars(string input)
26 {
27 for (unsigned int i=1; i<input.length(); i+=2)
28 {
29 char tmp = input[i];
30 input[i] = input[i-1];
31 input[i-1] = tmp;
32 }
33 return input;
34 }
35
36 string EncodePhonenr(string input)
37 {
38 if ( (input.length() % 2) == 1)
39 input.append("F");
40 return SwitchChars(input);
41 }
42
43 string DecodePhonenr(string input)
44 {
45 input = SwitchChars(input);
46 int last = input.length() -1;
47
48 if (input.at(last) == 'F')
49 input.erase(last,1);
50 return input;
51 }
52
53
54
55
56 string HexformatVector(vector<unsigned char> vec)
57 {
58 ostringstream os;
59
60 for (unsigned int i=0; i<vec.size(); ++i)
61 {
62 os.width(2);
63 os.fill('0');
64 os << hex << uppercase << static_cast<unsigned int>(vec.at(i));
65 }
66
67
68 return os.str();
69 }
70
71 std::string Decode8to7bit(vector<unsigned char> input)
72 {
73 string result;
74
75 int shift = 0;
76 for (unsigned int i=0; i<input.size(); ++i)
77 {
78 unsigned char current = input.at(i);
79 unsigned char prev = (i>0) ? input.at(i-1) : 0;
80
81 current <<= shift;
82
83 prev >>= (8-shift);
84
85 unsigned char byte = current | prev;
86 byte &= 0x7F;
87
88 result.append(1, byte);
89
90 if (shift == 6)
91 result.append(1, input.at(i) >> 1);
92
93 shift = (shift+1) % 7;
94
95 }
96
97 return result;
98 }
99
100
101
102
103 vector<unsigned char> Encode7to8bit(std::string str)
104 {
105 vector<unsigned char> buf;
106
107 int shift = 0;
108 for (unsigned int i=0; i<str.size(); ++i)
109 {
110 unsigned char current = str.at(i) & 0x7F;
111 unsigned char next = ( (i+1)<str.size()) ? str.at(i+1) : 0;
112 next &= 0x7F;
113
114 current >>= shift;
115 next <<= (7-shift);
116
117 unsigned char byte = current | next;
118 buf.push_back(byte);
119
120 if (shift == 6)
121 i++;
122
123 shift = (shift+1) % 7;
124
125 }
126
127 return buf;
128 }
129
130 vector<PduInfo> CreateSmsPdu(string to, string message, bool allowMultipart)
131 {
132 bool multipart = allowMultipart && message.length() > 160;
133
134 const unsigned char UDHI = multipart ? 0x40 : 0;
135
136 srand(time(0));
137 unsigned char csms_ref = rand() % 128;
138
139 int part_count;
140
141 const int PDU_LEN = 153;
142
143 if (multipart)
144 {
145 if (message.length() > 800)
146 {
147 Common::instance()->logMessage("Trying to send multipart sms > 800 bytes !!!");
148 message = message.substr(0,800);
149 }
150
151 part_count = message.length() / PDU_LEN;
152 if (message.length() % PDU_LEN)
153 part_count++;
154 }
155 else
156 {
157 part_count = 1;
158 }
159
160 vector<PduInfo> result;
161 for (int partnr = 0; partnr < part_count; ++partnr)
162 {
163 vector<unsigned char> pdu;
164
165 pdu.push_back(0x00); // use SMSC from phone
166 pdu.push_back( 0x01|UDHI ); // first octet -- no timeout
167 pdu.push_back(0x00); // TP-MR message reference
168 pdu.push_back(to.length() ); //length of phone nr
169 pdu.push_back(0x81); // type of address (international nr + ISDN/telephone range) - else try 0x81
170
171
172 string phone = EncodePhonenr(to);
173 pdu.insert( pdu.end(), phone.begin(), phone.end());
174
175 pdu.push_back(0x00); // Protocol identifier
176 pdu.push_back(0x00); // Data coding scheme
177
178 string message_part;
179 if (multipart)
180 {
181 message_part = message.substr(0, PDU_LEN);
182 message.erase(0, PDU_LEN);
183
184 pdu.push_back( message_part.length()+ 7 ); //UserDataLength
185 pdu.push_back( 0x06 ); // UDH Len
186 pdu.push_back( 0x00 ); // UDH Element Identifier
187 pdu.push_back( 0x03 ); // UDH element length
188 pdu.push_back( csms_ref ); // csms_ref reference
189 pdu.push_back( part_count );
190 pdu.push_back( partnr+1 );
191 pdu.push_back( 0x00);
192
193 }
194 else
195 {
196 if (message.length() > 160)
197 {
198 message_part = message.substr(0,160); //truncate to 160
199 Common::instance()->logMessage("Truncated message");
200 }
201 else
202 {
203 message_part = message;
204 }
205
206 pdu.push_back( message_part.length() ); //UserDataLength
207 }
208
209 vector<unsigned char> userData = Encode7to8bit(message_part);
210
211 pdu.insert( pdu.end(), userData.begin(), userData.end());
212
213 PduInfo info;
214 info.len = pdu.size()-1;
215 info.pdu = HexformatVector(pdu);
216 result.push_back(info);
217
218 }
219 return result;
220 }
221
222 }

  ViewVC Help
Powered by ViewVC 1.1.20