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

Diff of /smsdaemon/SmsPdu.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 62 by torben, Thu Jun 12 12:04:32 2008 UTC revision 73 by torben, Fri Jun 13 09:09:36 2008 UTC
# Line 10  Line 10 
10  #include <time.h>  #include <time.h>
11  #include <stdlib.h>  #include <stdlib.h>
12    
13    #include "common.h"
14  #include "util.h"  #include "util.h"
15    
16    #include <iostream>
17    
18  using namespace std;  using namespace std;
19    
# Line 21  namespace SmsPdu Line 22  namespace SmsPdu
22  {  {
23    
24    
 vector<unsigned char> BcdEncode(string input)  
 {  
         char buf[2] = " ";  
         vector<unsigned char> result;  
25    
26          unsigned char current;          string SwitchChars(string input)
         for (unsigned int i=0; i<input.length(); ++i)  
27          {          {
28                  buf[0] = input.at(i);                  for (unsigned int i=1; i<input.length(); i+=2)
29                  unsigned char tmp = atoi(buf);          {
30                            char tmp = input[i];
31                  if ( (i%2) == 0)                          input[i] = input[i-1];
32                  {                          input[i-1] = tmp;
                         current = tmp;  
                 }  
                 else  
                 {  
                         current |= (tmp<<4);  
                         result.push_back(current);  
33                  }                  }
34                    return input;
35          }          }
36    
37          if ((input.length() % 2) == 1)          string EncodePhonenr(string input)
38          {          {
39                  current |= 0xF0;                  if ( input.at(0) == '+' )
40                  result.push_back(current);                          input.erase(0,1);
41    
42                    if ( (input.length() % 2) == 1)
43                            input.append("F");
44                    return SwitchChars(input);
45            }
46    
47            string DecodePhonenr(string input)
48            {
49                    input = SwitchChars(input);
50                    int last = input.length() -1;
51    
52                    if (input.at(last) == 'F')
53                            input.erase(last,1);
54                    return input;
55          }          }
56    
         return result;  
 }  
57    
 string HexformatVector(vector<unsigned char> vec)  
 {  
         ostringstream os;  
58    
59          for (unsigned int i=0; i<vec.size(); ++i)  
60            string HexformatVector(vector<unsigned char> vec)
61          {          {
62                  os.width(2);                  ostringstream os;
                 os.fill('0');  
                 os << hex << uppercase << static_cast<unsigned int>(vec.at(i));  
         }  
63    
64                    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    
         return os.str();  
 }  
71    
72  std::string Encode8to7bit(vector<unsigned char> vec)                  return os.str();
73  {          }
         string result;  
74    
75          return result;          vector<unsigned char> HexDecodeString(string str)
76  }          {
77                    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    
81  vector<unsigned char> Encode7to8bit(std::string str)                  return vec;
82  {          }
         vector<unsigned char> buf;  
83    
84          int shift = 0;          std::string Decode8to7bit(vector<unsigned char> input, int shift_start)
         for (unsigned int i=0; i<str.size(); ++i)  
85          {          {
86                  unsigned char current = str.at(i) & 0x7F;                  string result;
                 unsigned char next = ( (i+1)<str.size()) ? str.at(i+1) : 0;  
                 next &= 0x7F;  
87    
88                  current >>= shift;                  int shift = shift_start;
89                  next <<= (7-shift);                  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    
94                  unsigned char byte = current | next;                          current <<= shift;
                 buf.push_back(byte);  
95    
96                  if (shift == 6)                          prev >>= (8-shift);
                         i++;  
97    
98                  shift = (shift+1) % 7;                          unsigned char byte = current | prev;
99                            byte &= 0x7F;
100    
101          }                          result.append(1, byte);
102    
103          return buf;                          if (shift == 6)
104  }                                  result.append(1, input.at(i) >> 1);
105    
106  vector<PduInfo> CreateSmsPdu(string to, string message, bool allowMultipart)                          shift = (shift+1) % 7;
 {  
         bool multipart = allowMultipart && message.length() > 160;  
107    
108          const unsigned char UDHI = multipart ? 0x40 : 0;                  }
109    
110          srand(time(0));                  return result;
111          unsigned char csms_ref = rand() % 128;          }
112    
         int part_count;  
113    
         const int PDU_LEN = 153;  
114    
115          if (multipart)  
116          {          vector<unsigned char> Encode7to8bit(std::string str, int shift_start)
                 part_count = message.length() / PDU_LEN;  
                 if (message.length() % PDU_LEN)  
                         part_count++;  
         }  
         else  
117          {          {
118                  part_count = 1;                  vector<unsigned char> buf;
119    
120                    int shift = shift_start;
121                    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    
127                            current >>= shift;
128                            next <<= (7-shift);
129    
130                            unsigned char byte = current | next;
131                            buf.push_back(byte);
132    
133                            if (shift == 6)
134                                    i++;
135    
136                            shift = (shift+1) % 7;
137    
138                    }
139    
140                    return buf;
141          }          }
142    
143          vector<PduInfo> result;          vector<PduInfo> CreateSmsPdu(string to, string message, bool allowMultipart)
         for (int partnr = 0; partnr < part_count; ++partnr)  
144          {          {
145                  vector<unsigned char> pdu;                  bool multipart = allowMultipart && message.length() > 160;
146    
147                  pdu.push_back(0x00); // use SMSC from phone                  const unsigned char UDHI = multipart ? 0x40 : 0;
                 pdu.push_back( 0x01|UDHI ); // first octet -- no timeout  
                 pdu.push_back(0x00); // TP-MR message reference  
                 pdu.push_back(to.length() ); //length of phone nr  
                 pdu.push_back(0x91); // type of address (international nr  + ISDN/telephone range) - else try 0x81  
148    
149                  vector<unsigned char> phone = BcdEncode(to);                  srand(time(0));
150                  pdu.insert( pdu.end(), phone.begin(), phone.end());                  unsigned char csms_ref = rand() % 128;
151    
152                  pdu.push_back(0x00); // Protocol identifier                  int part_count;
153                  pdu.push_back(0x00); // Data coding scheme  
154                    const int PDU_LEN = 153;
155    
                 string message_part;  
156                  if (multipart)                  if (multipart)
157                  {                  {
158                          message_part = message.substr(0, PDU_LEN);                          if (message.length() > 800)
159                          message.erase(0, PDU_LEN);                          {
160                                    Common::instance()->logMessage("Trying to send multipart sms > 800 bytes !!!");
161                                    message = message.substr(0,800);
162                            }
163    
164                            part_count = message.length() / PDU_LEN;
165                            if (message.length() % PDU_LEN)
166                                    part_count++;
167                    }
168                    else
169                    {
170                            part_count = 1;
171                    }
172    
173                    vector<PduInfo> result;
174                    for (int partnr = 0; partnr < part_count; ++partnr)
175                    {
176                            vector<unsigned char> pdu;
177    
178                          pdu.push_back( message_part.length()+ 7 );  //UserDataLength                          pdu.push_back(0x00); // use SMSC from phone
179                          pdu.push_back( 0x06 ); // UDH Len                          pdu.push_back( 0x01|UDHI ); // first octet -- no timeout
180                          pdu.push_back( 0x00 ); // UDH Element Identifier                          pdu.push_back(0x00); // TP-MR message reference
181                          pdu.push_back( 0x03 ); // UDH element length                          pdu.push_back(to.length() ); //length of phone nr
182                          pdu.push_back( csms_ref ); // csms_ref reference                          pdu.push_back(0x81); // type of address (international nr  + ISDN/telephone range) - else try 0x81
183                          pdu.push_back( part_count );  
184                          pdu.push_back( partnr+1 );  
185                          pdu.push_back( 0x00);                          vector<unsigned char> phone = HexDecodeString( EncodePhonenr(to ));
186                            pdu.insert( pdu.end(), phone.begin(), phone.end());
187    
188                            pdu.push_back(0x00); // Protocol identifier
189                            pdu.push_back(0x00); // Data coding scheme
190    
191                            int shift_start = 0;
192                            string message_part;
193                            if (multipart)
194                            {
195                                    message_part = message.substr(0, PDU_LEN);
196                                    message.erase(0, PDU_LEN);
197    
198                                    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                                    //shift_start = 6;
207                            }
208                            else
209                            {
210                                    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                            }
222    
223                            vector<unsigned char> userData = Encode7to8bit(message_part, shift_start);
224    
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                  }                  }
233                    return result;
234            }
235    
236            typedef vector<unsigned char>::iterator char_it;
237    
238            string DecodeRawPhonenr(char_it start, char_it end)
239            {
240                    ostringstream os;
241    
242                    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    
251            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                  else
270                            os << "+";
271    
272                    os.width(2);
273                    os.fill('0');
274                    os << (timezone & 0x7F);
275    
276                    return os.str();
277            }
278    
279    
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    
292                    bool UDHI = (deliver_first_octet & 0x40) > 0;
293    
294                    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    
310                    unsigned char data_len = (*it++);
311    
312                    int shift_start = 0;
313                    if (UDHI)
314                  {                  {
315                          message_part = message.substr(0,160); //truncate to 160                          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                          pdu.push_back( message_part.length() ); //UserDataLength                          shift_start = udh_len+1; //make the 8to7bit decode start with the right shift level
321                  }                  }
322                    cout << hex<< (int)(*it) << endl;;
323    
                 vector<unsigned char> userData = Encode7to8bit(message_part);  
324    
325                  pdu.insert( pdu.end(), userData.begin(), userData.end());                  vector<unsigned char> user_data;
326                    user_data.insert(user_data.end(), it, it+data_len);
327                  PduInfo info;                  
328                  info.len = pdu.size()-1;                  result.message = Decode8to7bit(user_data, shift_start);
329                  info.pdu = HexformatVector(pdu);                  
                 result.push_back(info);  
330    
331                    return result;
332          }          }
         return result;  
 }  
333    
334  }  }
335    

Legend:
Removed from v.62  
changed lines
  Added in v.73

  ViewVC Help
Powered by ViewVC 1.1.20