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

Diff of /smsdaemon/SmsPdu.cpp

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

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

Legend:
Removed from v.68  
changed lines
  Added in v.70

  ViewVC Help
Powered by ViewVC 1.1.20