89b2d41411cf8f3157fd8ea319a1613ed51603fe
[sip-router] / modules_k / sms / libsms_putsms.c
1 /*
2 SMS Server Tools
3 Copyright (C) 2000-2002 Stefan Frings
4
5 This program is free software unless you got it under another license directly
6 from the author. You can redistribute it and/or modify it under the terms of
7 the GNU General Public License as published by the Free Software Foundation.
8 Either version 2 of the License, or (at your option) any later version.
9
10 http://www.isis.de/members/~s.frings
11 mailto:s.frings@mail.isis.de
12  */
13
14
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18 #include <termios.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <syslog.h>
23 #include "sms_funcs.h"
24 #include "libsms_charset.h"
25 #include "libsms_modem.h"
26
27
28 int  sms_report_type;
29
30 static char hexa[16] = {
31         '0','1','2','3','4','5','6','7',
32         '8','9','A','B','C','D','E','F'
33         };
34
35
36 void swapchars(char* string, int len) /* Swaps every second character */
37 {
38         int position;
39         char c;
40
41         for (position=0; position<len-1; position+=2)
42         {
43                 c=string[position];
44                 string[position]=string[position+1];
45                 string[position+1]=c;
46         }
47 }
48
49
50
51
52 /* Work with the complex bit building to generate a 7 bit PDU string
53    encapsulated in 8 bit */
54 int ascii2pdu(char* ascii, int asciiLength, char* pdu, int cs_convert)
55 {
56         static char tmp[500];
57         int pdubitposition=0;
58         int pdubyteposition=0;
59         int character;
60         int bit;
61         int pdubitnr;
62         char converted;
63         unsigned char foo;
64
65         memset(tmp,0,asciiLength);
66         for (character=0;character<asciiLength;character++)
67         {
68                 if (cs_convert)
69                         converted=ascii2sms(ascii[character]);
70                 else
71                         converted=ascii[character];
72                 for (bit=0;bit<7;bit++)
73                 {
74                         pdubitnr=7*character+bit;
75                         pdubyteposition=pdubitnr/8;
76                         pdubitposition=pdubitnr%8;
77                         if (converted & (1<<bit))
78                                 tmp[pdubyteposition]=tmp[pdubyteposition]|(1<<pdubitposition);
79                         else
80                                 tmp[pdubyteposition]=tmp[pdubyteposition]&~(1<<pdubitposition);
81                 }
82         }
83         tmp[pdubyteposition+1]=0;
84         for (character=0;character<=pdubyteposition; character++)
85         {
86                 foo = tmp[character] ;
87                 pdu[2*character  ] = hexa[foo>>4];
88                 pdu[2*character+1] = hexa[foo&0x0f];
89         }
90         pdu[2*(pdubyteposition+1)]=0;
91         return 2*(pdubyteposition+1);
92 }
93
94
95
96
97 /* Create a HEX Dump */
98 int binary2pdu(char* binary, int length, char* pdu)
99 {
100         int character;
101         unsigned char foo;
102
103         for (character=0;character<length; character++)
104         {
105                 foo = binary[character];
106                 pdu[2*character  ] = hexa[foo>>4];
107                 pdu[2*character+1] = hexa[foo&0x0f];
108         }
109         pdu[2*length]=0;
110         return 2*length;
111 }
112
113
114
115
116 /* make the PDU string. The destination variable pdu has to be big enough. */
117 int make_pdu(struct sms_msg *msg, struct modem *mdm, char* pdu)
118 {
119         int  coding;
120         int  flags;
121         char tmp[500];
122         int  pdu_len=0;
123         int  foo;
124
125         memcpy(tmp,msg->to.s,msg->to.len);
126         foo = msg->to.len;
127         tmp[foo] = 0;
128         // terminate the number with F if the length is odd
129         if ( foo%2 ) {
130                 tmp[foo]='F';
131                 tmp[++foo] = 0;
132         }
133         // Swap every second character
134         swapchars(tmp,foo);
135         flags = 0x01;   /* SMS-Submit MS to SMSC */
136         if (sms_report_type!=NO_REPORT)
137                 flags |= 0x20 ; /* status report request */
138         coding=240+1; // Dummy + Class 1
139         if (mdm->mode!=MODE_OLD)
140                 flags+=16; // Validity field
141         /* concatenate the first part of the PDU string */
142         if (mdm->mode==MODE_OLD)
143                 pdu_len += sprintf(pdu,"%02X00%02X91%s00%02X%02X",flags,
144                         msg->to.len,tmp,coding,msg->text.len);
145         else
146                 pdu_len += sprintf(pdu,"00%02X00%02X91%s00%02XA7%02X",flags,
147                         msg->to.len,tmp,coding,msg->text.len);
148         /* Create the PDU string of the message */
149         /* pdu_len += binary2pdu(msg->text.s,msg->text.len,pdu+pdu_len); */
150         pdu_len += ascii2pdu(msg->text.s,msg->text.len,pdu+pdu_len,1/*convert*/);
151         /* concatenate the text to the PDU string */
152         return pdu_len;
153 }
154
155
156
157
158 /* search into modem reply for the sms id */
159 inline int fetch_sms_id(char *answer)
160 {
161         char *p;
162         int  id;
163
164         p = strstr(answer,"+CMGS:");
165         if (!p)
166                 goto error;
167         p += 6;
168         /* parse to the first digit */
169         while(p && *p && (*p==' ' || *p=='\r' || *p=='\n'))
170                 p++;
171         if (*p<'0' || *p>'9')
172                 goto error;
173         /* convert the number*/
174         id = 0;
175         while (p && *p>='0' && *p<='9')
176                 id = id*10 + *(p++)-'0';
177
178         return id;
179 error:
180         return -1;
181 }
182
183
184
185
186 /* send sms */
187 int putsms( struct sms_msg *sms_messg, struct modem *mdm)
188 {
189         char command[500];
190         char command2[500];
191         char answer[500];
192         char pdu[500];
193         int clen,clen2;
194         int retries;
195         int err_code;
196         int pdu_len;
197         int sms_id;
198
199         pdu_len = make_pdu(sms_messg, mdm, pdu);
200         if (mdm->mode==MODE_OLD)
201                 clen = sprintf(command,"AT+CMGS=%i\r",pdu_len/2);
202         else if (mdm->mode==MODE_ASCII)
203                 clen = sprintf(command,"AT+CMGS=\"+%.*s\"\r",sms_messg->to.len,
204                         sms_messg->to.s);
205         else
206                 clen = sprintf(command,"AT+CMGS=%i\r",pdu_len/2-1);
207
208         if (mdm->mode==MODE_ASCII)
209                 clen2=sprintf(command2,"%.*s\x1A",sms_messg->text.len,
210                 sms_messg->text.s);
211         else
212                 clen2=sprintf(command2,"%.*s\x1A",pdu_len,pdu);
213
214         sms_id = 0;
215         for(err_code=0,retries=0;err_code<2 && retries<mdm->retry; retries++)
216         {
217                 if (put_command(mdm,command,clen,answer,sizeof(answer),50,"\r\n> ")
218                 && put_command(mdm,command2,clen2,answer,sizeof(answer),1000,0)
219                 && strstr(answer,"OK") )
220                 {
221                         /* no error during sending and the modem said OK */
222                         err_code = 2;
223                         /* if reports were request, we have to fetch the sms id from
224                         the modem reply to keep trace of the status reports */
225                         if (sms_report_type!=NO_REPORT) {
226                                 sms_id = fetch_sms_id(answer);
227                                 if (sms_id==-1)
228                                         err_code = 1;
229                         }
230                 } else {
231                         /* we have an error */
232                         if (checkmodem(mdm)==-1) {
233                                 err_code = 0;
234                                 LM_WARN("resending last sms! \n");
235                         } else if (err_code==0) {
236                                 LM_WARN("possible corrupted sms. Let's try again!\n");
237                                 err_code = 1;
238                         }else {
239                                 LM_ERR("We have a FUBAR sms!! drop it!\n");
240                                 err_code = 3;
241                         }
242                 }
243         }
244
245         if (err_code==0)
246                 LM_WARN("something spooky is going on with the modem!"
247                         " Re-inited and re-tried for %d times without success!\n",
248                         mdm->retry);
249         return (err_code==0?-2:(err_code==2?sms_id:-1));
250 }
251