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

Annotation of /smsdaemon/SmsPdu.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 157 - (hide annotations) (download)
Mon Dec 8 21:28:40 2008 UTC (15 years, 5 months ago) by torben
File size: 6618 byte(s)
Move logpart to its own files

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

  ViewVC Help
Powered by ViewVC 1.1.20