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

Annotation of /smsdaemon/SmsPdu.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 69 - (hide annotations) (download)
Fri Jun 13 06:38:43 2008 UTC (15 years, 11 months ago) by torben
File size: 6068 byte(s)
Basic Sms PDU parsing works

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     if ( (input.length() % 2) == 1)
40     input.append("F");
41     return SwitchChars(input);
42     }
43 torben 61
44 torben 69 string DecodePhonenr(string input)
45     {
46     input = SwitchChars(input);
47     int last = input.length() -1;
48 torben 68
49 torben 69 if (input.at(last) == 'F')
50     input.erase(last,1);
51     return input;
52     }
53 torben 59
54 torben 68
55    
56    
57 torben 69 string HexformatVector(vector<unsigned char> vec)
58 torben 59 {
59 torben 69 ostringstream os;
60 torben 59
61 torben 69 for (unsigned int i=0; i<vec.size(); ++i)
62     {
63     os.width(2);
64     os.fill('0');
65     os << hex << uppercase << static_cast<unsigned int>(vec.at(i));
66     }
67 torben 59
68    
69 torben 69 return os.str();
70     }
71 torben 61
72 torben 69 vector<unsigned char> HexDecodeString(string str)
73 torben 68 {
74 torben 69 vector<unsigned char> vec;
75     for (unsigned int i=0; i<str.length(); i+=2)
76     vec.push_back( strtol( str.substr(i,2).c_str(), 0, 16 ));
77 torben 68
78 torben 69 return vec;
79     }
80 torben 68
81 torben 69 std::string Decode8to7bit(vector<unsigned char> input)
82     {
83     string result;
84 torben 68
85 torben 69 int shift = 0;
86     for (unsigned int i=0; i<input.size(); ++i)
87     {
88     unsigned char current = input.at(i);
89     unsigned char prev = (i>0) ? input.at(i-1) : 0;
90 torben 68
91 torben 69 current <<= shift;
92 torben 68
93 torben 69 prev >>= (8-shift);
94 torben 68
95 torben 69 unsigned char byte = current | prev;
96     byte &= 0x7F;
97 torben 68
98 torben 69 result.append(1, byte);
99 torben 68
100 torben 69 if (shift == 6)
101     result.append(1, input.at(i) >> 1);
102 torben 61
103 torben 69 shift = (shift+1) % 7;
104 torben 68
105 torben 69 }
106 torben 68
107 torben 69 return result;
108     }
109 torben 68
110 torben 59
111 torben 69
112    
113     vector<unsigned char> Encode7to8bit(std::string str)
114 torben 59 {
115 torben 69 vector<unsigned char> buf;
116 torben 59
117 torben 69 int shift = 0;
118     for (unsigned int i=0; i<str.size(); ++i)
119     {
120     unsigned char current = str.at(i) & 0x7F;
121     unsigned char next = ( (i+1)<str.size()) ? str.at(i+1) : 0;
122     next &= 0x7F;
123 torben 59
124 torben 69 current >>= shift;
125     next <<= (7-shift);
126 torben 59
127 torben 69 unsigned char byte = current | next;
128     buf.push_back(byte);
129 torben 59
130 torben 69 if (shift == 6)
131     i++;
132 torben 59
133 torben 69 shift = (shift+1) % 7;
134    
135     }
136    
137     return buf;
138 torben 59 }
139    
140 torben 69 vector<PduInfo> CreateSmsPdu(string to, string message, bool allowMultipart)
141     {
142     bool multipart = allowMultipart && message.length() > 160;
143 torben 59
144 torben 69 const unsigned char UDHI = multipart ? 0x40 : 0;
145 torben 59
146 torben 69 srand(time(0));
147     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     Common::instance()->logMessage("Trying to send multipart sms > 800 bytes !!!");
158     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 68
182 torben 69 string phone = EncodePhonenr(to);
183     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 69 string message_part;
189     if (multipart)
190     {
191     message_part = message.substr(0, PDU_LEN);
192     message.erase(0, PDU_LEN);
193 torben 60
194 torben 69 pdu.push_back( message_part.length()+ 7 ); //UserDataLength
195     pdu.push_back( 0x06 ); // UDH Len
196     pdu.push_back( 0x00 ); // UDH Element Identifier
197     pdu.push_back( 0x03 ); // UDH element length
198     pdu.push_back( csms_ref ); // csms_ref reference
199     pdu.push_back( part_count );
200     pdu.push_back( partnr+1 );
201     pdu.push_back( 0x00);
202 torben 60
203 torben 63 }
204     else
205     {
206 torben 69 if (message.length() > 160)
207     {
208     message_part = message.substr(0,160); //truncate to 160
209     Common::instance()->logMessage("Truncated message");
210     }
211     else
212     {
213     message_part = message;
214     }
215    
216     pdu.push_back( message_part.length() ); //UserDataLength
217 torben 63 }
218 torben 60
219 torben 69 vector<unsigned char> userData = Encode7to8bit(message_part);
220    
221     pdu.insert( pdu.end(), userData.begin(), userData.end());
222    
223     PduInfo info;
224     info.len = pdu.size()-1;
225     info.pdu = HexformatVector(pdu);
226     result.push_back(info);
227    
228 torben 60 }
229 torben 69 return result;
230     }
231 torben 60
232 torben 69 typedef vector<unsigned char>::iterator char_it;
233 torben 60
234 torben 69 string DecodeRawPhonenr(char_it start, char_it end)
235     {
236     ostringstream os;
237 torben 60
238 torben 69 for (char_it it = start; it != end; ++it)
239     {
240     os.width(2);
241     os.fill('0');
242     os << hex << (int)(*it);
243     }
244     return DecodePhonenr(os.str());
245     }
246 torben 60
247 torben 69 string DecodeTimestamp(char_it start, char_it end)
248     {
249     string stamp = DecodeRawPhonenr(start,end);
250    
251     ostringstream os;
252    
253     os << stamp.substr(0,2) << "/"; //year
254     os << stamp.substr(2,2) << "/"; //month
255     os << stamp.substr(4,2) << ","; //day
256     os << stamp.substr(6,2) << ":"; //hour
257     os << stamp.substr(8,2) << ":"; //minute
258     os << stamp.substr(10,2) ; //second
259    
260     int timezone = strtol(stamp.substr(12,2).c_str(), 0, 16);
261    
262    
263     if (timezone > 127)
264     os << "-";
265     else
266     os << "+";
267    
268     os.width(2);
269     os.fill('0');
270     os << (timezone & 0x7F);
271    
272     return os.str();
273 torben 60 }
274 torben 59
275 torben 69
276     SMS ParseSmsPdu(std::string pdu_str)
277     {
278     SMS result;
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     unsigned char sender_len = (*it++);
288     if ( (sender_len % 2) == 1)
289     sender_len++;
290    
291     ++it; //ignore Type-Of-Address
292    
293     result.sender = DecodeRawPhonenr( it, it+(sender_len/2) );
294    
295     it += (sender_len/2);
296     ++it; //protocol identifier
297     ++it; //Data encoding
298    
299     result.timestamp = DecodeTimestamp(it, it+7);
300     it += 7;
301    
302     unsigned char data_len = (*it++);
303    
304     vector<unsigned char> user_data;
305     user_data.insert(user_data.end(), it, it+data_len);
306    
307     result.message = Decode8to7bit(user_data);
308    
309    
310     return result;
311     }
312    
313 torben 59 }

  ViewVC Help
Powered by ViewVC 1.1.20