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

Annotation of /smsdaemon/SmsPdu.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 73 - (hide annotations) (download)
Fri Jun 13 09:09:36 2008 UTC (15 years, 11 months ago) by torben
File size: 6643 byte(s)
Fixed a bug in CreateSmsPdu() so it now uses EncodePhonenr() correctly

1 torben 59 /* using http://sourceforge.net/projects/libserial/
2     */
3    
4    
5 torben 60 #include "SmsPdu.h"
6    
7 torben 59 #include <string>
8     #include <sstream>
9    
10 torben 60 #include <time.h>
11     #include <stdlib.h>
12 torben 59
13 torben 63 #include "common.h"
14 torben 59 #include "util.h"
15    
16 torben 69 #include <iostream>
17 torben 59
18     using namespace std;
19    
20    
21     namespace SmsPdu
22     {
23    
24    
25 torben 68
26 torben 69 string SwitchChars(string input)
27 torben 59 {
28 torben 69 for (unsigned int i=1; i<input.length(); i+=2)
29     {
30     char tmp = input[i];
31     input[i] = input[i-1];
32     input[i-1] = tmp;
33     }
34     return input;
35 torben 59 }
36    
37 torben 69 string EncodePhonenr(string input)
38     {
39 torben 73 if ( input.at(0) == '+' )
40     input.erase(0,1);
41    
42 torben 69 if ( (input.length() % 2) == 1)
43     input.append("F");
44     return SwitchChars(input);
45     }
46 torben 61
47 torben 69 string DecodePhonenr(string input)
48     {
49     input = SwitchChars(input);
50     int last = input.length() -1;
51 torben 68
52 torben 69 if (input.at(last) == 'F')
53     input.erase(last,1);
54     return input;
55     }
56 torben 59
57 torben 68
58    
59    
60 torben 69 string HexformatVector(vector<unsigned char> vec)
61 torben 59 {
62 torben 69 ostringstream os;
63 torben 59
64 torben 69 for (unsigned int i=0; i<vec.size(); ++i)
65     {
66     os.width(2);
67     os.fill('0');
68     os << hex << uppercase << static_cast<unsigned int>(vec.at(i));
69     }
70 torben 59
71    
72 torben 69 return os.str();
73     }
74 torben 61
75 torben 69 vector<unsigned char> HexDecodeString(string str)
76 torben 68 {
77 torben 69 vector<unsigned char> vec;
78     for (unsigned int i=0; i<str.length(); i+=2)
79     vec.push_back( strtol( str.substr(i,2).c_str(), 0, 16 ));
80 torben 68
81 torben 69 return vec;
82     }
83 torben 68
84 torben 73 std::string Decode8to7bit(vector<unsigned char> input, int shift_start)
85 torben 69 {
86     string result;
87 torben 68
88 torben 70 int shift = shift_start;
89 torben 69 for (unsigned int i=0; i<input.size(); ++i)
90     {
91     unsigned char current = input.at(i);
92     unsigned char prev = (i>0) ? input.at(i-1) : 0;
93 torben 68
94 torben 69 current <<= shift;
95 torben 68
96 torben 69 prev >>= (8-shift);
97 torben 68
98 torben 69 unsigned char byte = current | prev;
99     byte &= 0x7F;
100 torben 68
101 torben 69 result.append(1, byte);
102 torben 68
103 torben 69 if (shift == 6)
104     result.append(1, input.at(i) >> 1);
105 torben 61
106 torben 69 shift = (shift+1) % 7;
107 torben 68
108 torben 69 }
109 torben 68
110 torben 69 return result;
111     }
112 torben 68
113 torben 59
114 torben 69
115    
116 torben 73 vector<unsigned char> Encode7to8bit(std::string str, int shift_start)
117 torben 59 {
118 torben 69 vector<unsigned char> buf;
119 torben 59
120 torben 73 int shift = shift_start;
121 torben 69 for (unsigned int i=0; i<str.size(); ++i)
122     {
123     unsigned char current = str.at(i) & 0x7F;
124     unsigned char next = ( (i+1)<str.size()) ? str.at(i+1) : 0;
125     next &= 0x7F;
126 torben 59
127 torben 69 current >>= shift;
128     next <<= (7-shift);
129 torben 59
130 torben 69 unsigned char byte = current | next;
131     buf.push_back(byte);
132 torben 59
133 torben 69 if (shift == 6)
134     i++;
135 torben 59
136 torben 69 shift = (shift+1) % 7;
137    
138     }
139    
140     return buf;
141 torben 59 }
142    
143 torben 69 vector<PduInfo> CreateSmsPdu(string to, string message, bool allowMultipart)
144     {
145     bool multipart = allowMultipart && message.length() > 160;
146 torben 59
147 torben 69 const unsigned char UDHI = multipart ? 0x40 : 0;
148 torben 59
149 torben 69 srand(time(0));
150     unsigned char csms_ref = rand() % 128;
151 torben 59
152 torben 69 int part_count;
153 torben 59
154 torben 69 const int PDU_LEN = 153;
155 torben 61
156 torben 69 if (multipart)
157     {
158     if (message.length() > 800)
159     {
160     Common::instance()->logMessage("Trying to send multipart sms > 800 bytes !!!");
161     message = message.substr(0,800);
162     }
163 torben 61
164 torben 69 part_count = message.length() / PDU_LEN;
165     if (message.length() % PDU_LEN)
166     part_count++;
167     }
168     else
169 torben 65 {
170 torben 69 part_count = 1;
171 torben 65 }
172    
173 torben 69 vector<PduInfo> result;
174     for (int partnr = 0; partnr < part_count; ++partnr)
175     {
176     vector<unsigned char> pdu;
177 torben 59
178 torben 69 pdu.push_back(0x00); // use SMSC from phone
179     pdu.push_back( 0x01|UDHI ); // first octet -- no timeout
180     pdu.push_back(0x00); // TP-MR message reference
181     pdu.push_back(to.length() ); //length of phone nr
182     pdu.push_back(0x81); // type of address (international nr + ISDN/telephone range) - else try 0x81
183 torben 59
184 torben 73
185     vector<unsigned char> phone = HexDecodeString( EncodePhonenr(to ));
186 torben 69 pdu.insert( pdu.end(), phone.begin(), phone.end());
187 torben 60
188 torben 69 pdu.push_back(0x00); // Protocol identifier
189     pdu.push_back(0x00); // Data coding scheme
190 torben 60
191 torben 73 int shift_start = 0;
192 torben 69 string message_part;
193     if (multipart)
194     {
195     message_part = message.substr(0, PDU_LEN);
196     message.erase(0, PDU_LEN);
197 torben 60
198 torben 69 pdu.push_back( message_part.length()+ 7 ); //UserDataLength
199     pdu.push_back( 0x06 ); // UDH Len
200     pdu.push_back( 0x00 ); // UDH Element Identifier
201     pdu.push_back( 0x03 ); // UDH element length
202     pdu.push_back( csms_ref ); // csms_ref reference
203     pdu.push_back( part_count );
204     pdu.push_back( partnr+1 );
205     pdu.push_back( 0x00);
206 torben 73 //shift_start = 6;
207 torben 63 }
208     else
209     {
210 torben 69 if (message.length() > 160)
211     {
212     message_part = message.substr(0,160); //truncate to 160
213     Common::instance()->logMessage("Truncated message");
214     }
215     else
216     {
217     message_part = message;
218     }
219    
220     pdu.push_back( message_part.length() ); //UserDataLength
221 torben 63 }
222 torben 60
223 torben 73 vector<unsigned char> userData = Encode7to8bit(message_part, shift_start);
224 torben 69
225     pdu.insert( pdu.end(), userData.begin(), userData.end());
226    
227     PduInfo info;
228     info.len = pdu.size()-1;
229     info.pdu = HexformatVector(pdu);
230     result.push_back(info);
231    
232 torben 60 }
233 torben 69 return result;
234     }
235 torben 60
236 torben 69 typedef vector<unsigned char>::iterator char_it;
237 torben 60
238 torben 69 string DecodeRawPhonenr(char_it start, char_it end)
239     {
240     ostringstream os;
241 torben 60
242 torben 69 for (char_it it = start; it != end; ++it)
243     {
244     os.width(2);
245     os.fill('0');
246     os << hex << (int)(*it);
247     }
248     return DecodePhonenr(os.str());
249     }
250 torben 60
251 torben 69 string DecodeTimestamp(char_it start, char_it end)
252     {
253     string stamp = DecodeRawPhonenr(start,end);
254    
255     ostringstream os;
256    
257     os << stamp.substr(0,2) << "/"; //year
258     os << stamp.substr(2,2) << "/"; //month
259     os << stamp.substr(4,2) << ","; //day
260     os << stamp.substr(6,2) << ":"; //hour
261     os << stamp.substr(8,2) << ":"; //minute
262     os << stamp.substr(10,2) ; //second
263    
264     int timezone = strtol(stamp.substr(12,2).c_str(), 0, 16);
265    
266    
267     if (timezone > 127)
268     os << "-";
269     else
270     os << "+";
271    
272     os.width(2);
273     os.fill('0');
274     os << (timezone & 0x7F);
275    
276     return os.str();
277 torben 60 }
278 torben 59
279 torben 69
280     SMS ParseSmsPdu(std::string pdu_str)
281     {
282     SMS result;
283    
284     vector<unsigned char> pdu = HexDecodeString(pdu_str);
285    
286     vector<unsigned char>::iterator it = pdu.begin();
287    
288     it += (*it++); // Skip smsc info
289    
290     unsigned char deliver_first_octet = (*it++);
291 torben 70
292     bool UDHI = (deliver_first_octet & 0x40) > 0;
293    
294 torben 69 unsigned char sender_len = (*it++);
295     if ( (sender_len % 2) == 1)
296     sender_len++;
297    
298     ++it; //ignore Type-Of-Address
299    
300     result.sender = DecodeRawPhonenr( it, it+(sender_len/2) );
301    
302     it += (sender_len/2);
303     ++it; //protocol identifier
304     ++it; //Data encoding
305    
306     result.timestamp = DecodeTimestamp(it, it+7);
307     it += 7;
308    
309 torben 70
310 torben 69 unsigned char data_len = (*it++);
311    
312 torben 70 int shift_start = 0;
313     if (UDHI)
314     {
315     int udh_len = (*it++);
316     cout << "UDH_LEN:" << udh_len << endl;
317     it += udh_len; //just ignore the User Data Header
318     data_len -= udh_len;
319    
320     shift_start = udh_len+1; //make the 8to7bit decode start with the right shift level
321     }
322     cout << hex<< (int)(*it) << endl;;
323    
324    
325 torben 69 vector<unsigned char> user_data;
326     user_data.insert(user_data.end(), it, it+data_len);
327    
328 torben 70 result.message = Decode8to7bit(user_data, shift_start);
329 torben 69
330    
331     return result;
332     }
333    
334 torben 59 }

  ViewVC Help
Powered by ViewVC 1.1.20