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

Diff of /smsdaemon/SmsPdu.cpp

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

revision 59 by torben, Wed Jun 11 19:42:24 2008 UTC revision 73 by torben, Fri Jun 13 09:09:36 2008 UTC
# Line 2  Line 2 
2   */   */
3    
4    
5    #include "SmsPdu.h"
6    
7  #include <string>  #include <string>
8  #include <sstream>  #include <sstream>
9    
10    #include <time.h>
11    #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 18  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)
27          for (unsigned int i=0; i<input.length(); ++i)          {
28                    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            }
36    
37            string EncodePhonenr(string input)
38            {
39                    if ( input.at(0) == '+' )
40                            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    
57    
58    
59    
60            string HexformatVector(vector<unsigned char> vec)
61            {
62                    ostringstream os;
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    
71    
72                    return os.str();
73            }
74    
75            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                    return vec;
82            }
83    
84            std::string Decode8to7bit(vector<unsigned char> input, int shift_start)
85            {
86                    string result;
87    
88                    int shift = shift_start;
89                    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                            current <<= shift;
95    
96                            prev >>= (8-shift);
97    
98                            unsigned char byte = current | prev;
99                            byte &= 0x7F;
100    
101                            result.append(1, byte);
102    
103                            if (shift == 6)
104                                    result.append(1, input.at(i) >> 1);
105    
106                            shift = (shift+1) % 7;
107    
108                    }
109    
110                    return result;
111            }
112    
113    
114    
115    
116            vector<unsigned char> Encode7to8bit(std::string str, int shift_start)
117          {          {
118                  buf[0] = input.at(i);                  vector<unsigned char> buf;
                 unsigned char tmp = atoi(buf);  
119    
120                  if ( (i%2) == 0)                  int shift = shift_start;
121                    for (unsigned int i=0; i<str.size(); ++i)
122                  {                  {
123                          current = tmp;                          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> CreateSmsPdu(string to, string message, bool allowMultipart)
144            {
145                    bool multipart = allowMultipart && message.length() > 160;
146    
147                    const unsigned char UDHI = multipart ? 0x40 : 0;
148    
149                    srand(time(0));
150                    unsigned char csms_ref = rand() % 128;
151    
152                    int part_count;
153    
154                    const int PDU_LEN = 153;
155    
156                    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    
164                            part_count = message.length() / PDU_LEN;
165                            if (message.length() % PDU_LEN)
166                                    part_count++;
167                  }                  }
168                  else                  else
169                  {                  {
170                          current |= (tmp<<4);                          part_count = 1;
171                          result.push_back(current);                  }
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(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    
184    
185                            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          return result;          typedef vector<unsigned char>::iterator char_it;
 }  
237    
238  string HexformatVector(vector<unsigned char> vec)          string DecodeRawPhonenr(char_it start, char_it end)
239  {          {
240          ostringstream os;                  ostringstream os;
241    
242          for (unsigned int i=0; i<vec.size(); ++i)                  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
270                            os << "+";
271    
272                  os.width(2);                  os.width(2);
273                  os.fill('0');                  os.fill('0');
274                  os << hex << uppercase << static_cast<unsigned int>(vec.at(i));                  os << (timezone & 0x7F);
275    
276                    return os.str();
277          }          }
278    
279    
280          return os.str();          SMS ParseSmsPdu(std::string pdu_str)
281  }          {
282                    SMS result;
283    
284  vector<unsigned char> Encode7to8bit(std::string str)                  vector<unsigned char> pdu = HexDecodeString(pdu_str);
 {  
         vector<unsigned char> buf;  
285    
286          int shift = 0;                  vector<unsigned char>::iterator it = pdu.begin();
         for (unsigned int i=0; i<str.size(); ++i)  
         {  
                 unsigned char current = str.at(i) & 0x7F;  
                 unsigned char next = ( (i+1)<str.size()) ? str.at(i+1) : 0;  
                 next &= 0x7F;  
287    
288                  current >>= shift;                  it += (*it++); // Skip smsc info
                 next <<= (7-shift);  
289    
290                  unsigned char byte = current | next;                  unsigned char deliver_first_octet = (*it++);
                 buf.push_back(byte);  
291    
292                  if (shift == 6)                  bool UDHI = (deliver_first_octet & 0x40) > 0;
                         i++;  
293    
294                  shift = (shift+1) % 7;                  unsigned char sender_len = (*it++);
295                    if ( (sender_len % 2) == 1)
296                            sender_len++;
297    
298          }                  ++it; //ignore Type-Of-Address
299    
300          return buf;                  result.sender = DecodeRawPhonenr( it, it+(sender_len/2) );
 }  
301    
302  string CreateSmsPdu(string to, string message, int& len)                  it += (sender_len/2);
303  {                  ++it; //protocol identifier
304          message = message.substr(0,160); //truncate to 160                  ++it; //Data encoding
305    
306          vector<unsigned char> pdu;                  result.timestamp = DecodeTimestamp(it, it+7);
307                    it += 7;
308    
         pdu.push_back(0x00); // use SMSC from phone  
         pdu.push_back(0x01); // 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  
309    
310          vector<unsigned char> phone = BcdEncode(to);                  unsigned char data_len = (*it++);
         pdu.insert( pdu.end(), phone.begin(), phone.end());  
311    
312          pdu.push_back(0x00); // Protocol identifier                  int shift_start = 0;
313          pdu.push_back(0x00); // Data coding scheme                  if (UDHI)
314          pdu.push_back( message.length() ); //UserDataLength                  {
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          vector<unsigned char> userData = Encode7to8bit(message);                          shift_start = udh_len+1; //make the 8to7bit decode start with the right shift level
321          pdu.insert( pdu.end(), userData.begin(), userData.end());                  }
322                    cout << hex<< (int)(*it) << endl;;
323    
324          len = pdu.size()-1;  
325          return HexformatVector(pdu);                  vector<unsigned char> user_data;
326  }                  user_data.insert(user_data.end(), it, it+data_len);
327                    
328                    result.message = Decode8to7bit(user_data, shift_start);
329                    
330    
331                    return result;
332            }
333    
334  }  }
335    

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

  ViewVC Help
Powered by ViewVC 1.1.20