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