sms(s): delete after copy to common directory
[sip-router] / modules_k / sms / sms_funcs.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * Kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License 
19  * along with this program; if not, write to the Free Software 
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  * History:
23  * --------
24  * 2003-01-23: switched from t_uac to t_uac_dlg, adapted to new way of
25  *              parsing for Content-Type (bogdan)
26  * 2003-02-28: protocolization of t_uac_dlg completed (jiri)
27  * 2003-08-05: adapted to the new parse_content_type_hdr function (bogdan)
28  * 2003-09-11: updated to new build_lump_rpl() interface (bogdan)
29  * 2003-09-11: force parsing to hdr when extracting destination user (bogdan)
30  */
31
32 #include <unistd.h>
33 #include <errno.h>
34 #include <stdlib.h>
35 #include "../../dprint.h"
36 #include "../../ut.h"
37 #include "../../config.h"
38 #include "../../globals.h"
39 #include "../../mem/mem.h"
40 #include "../../mem/shm_mem.h"
41 #include "../../parser/parse_uri.h"
42 #include "../../parser/parse_content.h"
43 #include "../../parser/parse_from.h"
44 #include "../../data_lump_rpl.h"
45 #include "../../lib/kcore/km_ut.h"
46 #include "../../modules/tm/t_hooks.h"
47 #include "../../modules/tm/uac.h"
48 #include "sms_funcs.h"
49 #include "sms_report.h"
50 #include "libsms_modem.h"
51 #include "libsms_sms.h"
52
53
54
55
56 struct modem modems[MAX_MODEMS];
57 struct network networks[MAX_NETWORKS];
58 int net_pipes_in[MAX_NETWORKS];
59 int nr_of_networks;
60 int nr_of_modems;
61 int max_sms_parts;
62 int *queued_msgs;
63 int use_contact;
64 struct tm_binds tmb;
65
66
67 #define ERR_NUMBER_TEXT " is an invalid number! Please resend your SMS "\
68         "using a number in +(country code)(area code)(local number) format. Thanks"\
69         " for using our service!"
70 #define ERR_NUMBER_TEXT_LEN (sizeof(ERR_NUMBER_TEXT)-1)
71
72 #define ERR_TRUNCATE_TEXT "We are sorry, but your message exceeded our "\
73         "maximum allowed length. The following part of the message wasn't sent"\
74         " : "
75 #define ERR_TRUNCATE_TEXT_LEN (sizeof(ERR_TRUNCATE_TEXT)-1)
76
77 #define ERR_MODEM_TEXT "Due to our modem temporary indisponibility, "\
78         "the following message couldn't be sent : "
79 #define ERR_MODEM_TEXT_LEN (sizeof(ERR_MODEM_TEXT)-1)
80
81 #define STORED_NOTE "NOTE: Your SMS received provisional confirmation"\
82         " 48 \"Delivery is not yet possible\". The SMS was store on the "\
83         "SMSCenter for further delivery. Our gateway cannot guarantee "\
84         "further information regarding your SMS delivery! Your message was: "
85 #define STORED_NOTE_LEN  (sizeof(STORED_NOTE)-1)
86
87 #define OK_MSG "Your SMS was finally successfully delivered!"\
88         " Your message was: "
89 #define OK_MSG_LEN  (sizeof(OK_MSG)-1)
90
91 #define CONTENT_TYPE_HDR     "Content-Type: text/plain"
92 #define CONTENT_TYPE_HDR_LEN (sizeof(CONTENT_TYPE_HDR)-1)
93
94 #define is_in_sip_addr(_p) \
95         ((_p)!=' ' && (_p)!='\t' && (_p)!='(' && (_p)!='[' && (_p)!='<' \
96         && (_p)!='>' && (_p)!=']' && (_p)!=')' && (_p)!='?' && (_p)!='!' \
97         && (_p)!=';' && (_p)!=',' && (_p)!='\n' && (_p)!='\r' && (_p)!='=')
98
99 #define no_sip_addr_begin(_p) \
100         ( (_p)!=' ' && (_p)!='\t' && (_p)!='-' && (_p)!='=' && (_p)!='\r'\
101         && (_p)!='\n' && (_p)!=';' && (_p)!=',' && (_p)!='.' && (_p)!=':')
102
103
104
105 int push_on_network(struct sip_msg *msg, int net)
106 {
107         str    body;
108         struct sip_uri  uri;
109         struct sms_msg  *sms_messg;
110         struct to_body  *from;
111         char   *p;
112         int    len;
113         int    mime;
114
115         /* get the message's body
116          * anyhow we have to call this function, so let's do it at the beginning
117          * to force the parsing of all the headers - like this we avoid separate
118          * calls of parse_headers function for FROM, CONTENT_LENGTH, TO hdrs  */
119         body.s = get_body( msg );
120         if (body.s==0) {
121                 LM_ERR("failed to extract body from msg!\n");
122                 goto error;
123         }
124
125         /* content-length (if present) must be already parsed */
126         if (!msg->content_length) {
127                 LM_ERR("no Content-Length header found!\n");
128                 goto error;
129         }
130         body.len = get_content_length( msg );
131
132         /* parse the content-type header */
133         if ( (mime=parse_content_type_hdr(msg))<1 ) {
134                 LM_ERR("failed to parse Content-Type header\n");
135                 goto error;
136         }
137
138         /* check the content-type value */
139         if ( mime!=(TYPE_TEXT<<16)+SUBTYPE_PLAIN
140         && mime!=(TYPE_MESSAGE<<16)+SUBTYPE_CPIM ) {
141                 LM_ERR("invalid content-type for a message request! type found=%d\n",
142                                 mime);
143                 goto error;
144         }
145
146         /* we try to get the user name (phone number) first from the RURI 
147            (in our case means from new_uri or from first_line.u.request.uri);
148            if it's missing there (like in requests generated by MSN MESSENGER),
149            we go for "to" header
150         */
151         LM_DBG("string to get user from new_uri\n");
152         if ( !msg->new_uri.s||parse_uri( msg->new_uri.s,msg->new_uri.len,&uri)
153         || !uri.user.len )
154         {
155                 LM_DBG("string to get user from R_uri\n");
156                 if ( parse_uri( msg->first_line.u.request.uri.s,
157                 msg->first_line.u.request.uri.len ,&uri)||!uri.user.len )
158                 {
159                         LM_DBG("string to get user from To\n");
160                         if ((!msg->to&&((parse_headers(msg,HDR_TO_F,0)==-1)||!msg->to)) ||
161                         parse_uri( get_to(msg)->uri.s, get_to(msg)->uri.len, &uri)<0
162                         || !uri.user.len)
163                         {
164                                 LM_ERR("failed to extract user name from RURI"
165                                                 " and To header!\n");
166                                 goto error;
167                         }
168                 }
169         }
170         /* check the uri.user format = '+(inter code)(number)' */
171         if (uri.user.len<2 || uri.user.s[0]!='+' || uri.user.s[1]<'1'
172         || uri.user.s[1]>'9') {
173                 LM_ERR("user tel number [%.*s] does not respect international format\n"
174                                 ,uri.user.len,uri.user.s);
175                 goto error;
176         }
177
178         /* parsing from header */
179         if ( parse_from_header( msg )<0 ) {
180                 LM_ERR("failed get FROM header\n");
181                 goto error;
182         }
183         from = (struct to_body*)msg->from->parsed;
184
185         /*-------------BUILD AND FILL THE SMS_MSG STRUCTURE --------------------*/
186         /* computes the amount of memory needed */
187         len = SMS_HDR_BF_ADDR_LEN + from->uri.len
188                 + SMS_HDR_AF_ADDR_LEN + body.len + SMS_FOOTER_LEN /*text to send*/
189                 + from->uri.len /* from */
190                 + uri.user.len-1 /* to user (without '+') */
191                 + sizeof(struct sms_msg) ; /* the sms_msg structure */
192         /* allocs a new sms_msg structure in shared memory */
193         sms_messg = (struct sms_msg*)shm_malloc(len);
194         if (!sms_messg) {
195                 LM_ERR("failed get shm memory!\n");
196                 goto error;
197         }
198         p = (char*)sms_messg + sizeof(struct sms_msg);
199
200         /* copy "from" into sms struct */
201         sms_messg->from.len = from->uri.len;
202         sms_messg->from.s = p;
203         append_str(p,from->uri.s,from->uri.len);
204
205         /* copy "to.user" - we have to strip out the '+' */
206         sms_messg->to.len = uri.user.len-1;
207         sms_messg->to.s = p;
208         append_str(p,uri.user.s+1,sms_messg->to.len);
209
210         /* copy (and composing) sms body */
211         sms_messg->text.len = SMS_HDR_BF_ADDR_LEN + sms_messg->from.len
212                 + SMS_HDR_AF_ADDR_LEN + body.len+SMS_FOOTER_LEN;
213         sms_messg->text.s = p;
214         append_str(p, SMS_HDR_BF_ADDR, SMS_HDR_BF_ADDR_LEN);
215         append_str(p, sms_messg->from.s, sms_messg->from.len);
216         append_str(p, SMS_HDR_AF_ADDR, SMS_HDR_AF_ADDR_LEN);
217         append_str(p, body.s, body.len);
218         append_str(p, SMS_FOOTER, SMS_FOOTER_LEN);
219
220         if (*queued_msgs>MAX_QUEUED_MESSAGES)
221                 goto error;
222         (*queued_msgs)++;
223
224         if (write(net_pipes_in[net], &sms_messg, sizeof(sms_messg))!=
225         sizeof(sms_messg) )
226         {
227                 LM_ERR("failed to write for net %d to pipe [%d] : %s\n",
228                                 net,net_pipes_in[net],strerror(errno) );
229                 shm_free(sms_messg);
230                 (*queued_msgs)--;
231                 goto error;
232         }
233
234         return 1;
235  error:
236         return -1;
237 }
238
239
240
241
242
243 int send_sip_msg_request(str *to, str *from_user, str *body)
244 {
245         str msg_type = { "MESSAGE", 7};
246         str from;
247         str hdrs;
248         int foo;
249         char *p;
250         uac_req_t uac_r;
251
252         from.s = hdrs.s = 0;
253         from.len = hdrs.len = 0;
254
255         /* From header */
256         from.len = 6 /*"<sip:+"*/ +  from_user->len/*user*/ + 1/*"@"*/
257                 + domain.len /*host*/ + 1 /*">"*/ ;
258         from.s = (char*)pkg_malloc(from.len);
259         if (!from.s)
260                 goto error;
261         p=from.s;
262         append_str(p,"<sip:+",6);
263         append_str(p,from_user->s,from_user->len);
264         *(p++)='@';
265         append_str(p,domain.s,domain.len);
266         *(p++)='>';
267
268         /* hdrs = Contact header + Content-type */
269         /* length */
270         hdrs.len = CONTENT_TYPE_HDR_LEN + CRLF_LEN;
271         if (use_contact)
272                 hdrs.len += 15 /*"Contact: <sip:+"*/ + from_user->len/*user*/ +
273                         1/*"@"*/ + domain.len/*host*/ + 1 /*">"*/ + CRLF_LEN;
274         hdrs.s = (char*)pkg_malloc(hdrs.len);
275         if (!hdrs.s)
276                 goto error;
277         p=hdrs.s;
278         append_str(p,CONTENT_TYPE_HDR,CONTENT_TYPE_HDR_LEN);
279         append_str(p,CRLF,CRLF_LEN);
280         if (use_contact) {
281                 append_str(p,"Contact: <sip:+",15);
282                 append_str(p,from_user->s,from_user->len);
283                 *(p++)='@';
284                 append_str(p,domain.s,domain.len);
285                 append_str(p,">"CRLF,1+CRLF_LEN);
286         }
287
288         /* sending the request */
289         set_uac_req(&uac_r, &msg_type, &hdrs, body, 0, 0, 0, 0);
290         foo = tmb.t_request( &uac_r,
291                         0,                        /* Request-URI */
292                         to,                       /* To */
293                         &from,                    /* From */
294                         0                        /* outbound uri */
295                 );
296         if (from.s) pkg_free(from.s);
297         if (hdrs.s) pkg_free(hdrs.s);
298         return foo;
299 error:
300         LM_ERR("no more pkg memory!\n");
301         if (from.s) pkg_free(from.s);
302         if (hdrs.s) pkg_free(hdrs.s);
303         return -1;
304 }
305
306
307
308
309 inline int send_error(struct sms_msg *sms_messg, char *msg1_s, int msg1_len,
310                                                                                                         char *msg2_s, int msg2_len)
311 {
312         str  body;
313         char *p;
314         int  foo;
315
316         /* body */
317         body.len = msg1_len + msg2_len;
318         body.s = (char*)pkg_malloc(body.len);
319         if (!body.s)
320                 goto error;
321         p=body.s;
322         append_str(p, msg1_s, msg1_len );
323         append_str(p, msg2_s, msg2_len);
324
325         /* sending */
326         foo = send_sip_msg_request( &(sms_messg->from), &(sms_messg->to), &body);
327         pkg_free( body.s );
328         return foo;
329 error:
330         LM_ERR("no more pkg memory!\n");
331         return -1;
332
333 }
334
335
336
337 inline unsigned int split_text(str *text, unsigned char *lens,int nice)
338 {
339         int  nr_chunks;
340         int  k,k1,len;
341         char c;
342
343         nr_chunks = 0;
344         len = 0;
345
346         do{
347                 k = MAX_SMS_LENGTH-(nice&&nr_chunks?SMS_EDGE_PART_LEN:0);
348                 if ( len+k<text->len ) {
349                         /* is not the last piece :-( */
350                         if (nice && !nr_chunks) k -= SMS_EDGE_PART_LEN;
351                         if (text->len-len-k<=SMS_FOOTER_LEN+4)
352                                 k = (text->len-len)/2;
353                         /* ->looks for a point to split */
354                         k1 = k;
355                         while( k>0 && (c=text->s[len+k-1])!='.' && c!=' ' && c!=';'
356                         && c!='\r' && c!='\n' && c!='-' && c!='!' && c!='?' && c!='+'
357                         && c!='=' && c!='\t' && c!='\'')
358                                 k--;
359                         if (k<k1/2)
360                                 /* wast of space !!!!*/
361                                 k=k1;
362                         len += k;
363                         lens[nr_chunks] = k;
364                 }else {
365                         /*last chunk*/
366                         lens[nr_chunks] = text->len-len;
367                         len = text->len;
368                 }
369                 nr_chunks++;
370         }while (len<text->len);
371
372         return nr_chunks;
373 }
374
375
376
377
378 int send_as_sms(struct sms_msg *sms_messg, struct modem *mdm)
379 {
380         static char   buf[MAX_SMS_LENGTH];
381         unsigned int  buf_len;
382         unsigned char len_array_1[256], len_array_2[256], *len_array;
383         unsigned int  nr_chunks_1,  nr_chunks_2, nr_chunks;
384         unsigned int  use_nice;
385         str  text;
386         char *p, *q;
387         int  ret_code;
388         int  i;
389
390         text.s   = sms_messg->text.s;
391         text.len = sms_messg->text.len;
392
393         nr_chunks_1 = split_text( &text, len_array_1, 0);
394         nr_chunks_2 = split_text( &text, len_array_2, 1);
395         if (nr_chunks_1==nr_chunks_2) {
396                 len_array = len_array_2;
397                 nr_chunks = nr_chunks_2;
398                 use_nice = 1;
399         } else {
400                 len_array = len_array_1;
401                 nr_chunks = nr_chunks_1;
402                 use_nice = 0;
403         }
404
405         sms_messg->ref = 1;
406         for(i=0,p=text.s ; i<nr_chunks&&i<max_sms_parts ; p+=len_array[i++]) {
407                 if (use_nice) {
408                         q = buf;
409                         if (nr_chunks>1 && i)  {
410                                 append_str(q,SMS_EDGE_PART,SMS_EDGE_PART_LEN);
411                                 *(q-2)=nr_chunks+'0';
412                                 *(q-4)=i+1+'0';
413                         }
414                         append_str(q,p,len_array[i]);
415                         if (nr_chunks>1 && !i)  {
416                                 append_str(q,SMS_EDGE_PART,SMS_EDGE_PART_LEN);
417                                 *(q-2)=nr_chunks+'0';
418                                 *(q-4)=i+1+'0';
419                         }
420                         buf_len = q-buf;
421                 } else {
422                         q = buf;
423                         append_str(q,p,len_array[i]);
424                         buf_len = len_array[i];
425                 }
426                 if (i+1==max_sms_parts && i+1<nr_chunks) {
427                         /* simply override the end of the last allowed part */
428                         buf_len += SMS_TRUNCATED_LEN+SMS_FOOTER_LEN;
429                         if (buf_len>MAX_SMS_LENGTH) buf_len = MAX_SMS_LENGTH;
430                         q = buf + (buf_len-SMS_TRUNCATED_LEN-SMS_FOOTER_LEN);
431                         append_str(q,SMS_TRUNCATED,SMS_TRUNCATED_LEN);
432                         append_str(q,SMS_FOOTER,SMS_FOOTER_LEN);
433                         p += buf_len-SMS_TRUNCATED_LEN-SMS_FOOTER_LEN-SMS_EDGE_PART_LEN;
434                         send_error(sms_messg, ERR_TRUNCATE_TEXT, ERR_TRUNCATE_TEXT_LEN,
435                                 p, text.len-(p-text.s)-SMS_FOOTER_LEN);
436                 }
437                 LM_DBG("---%d--<%d><%d>--\n|%.*s|\n", i, len_array[i], buf_len,
438                                                                                 (int)buf_len, buf);
439                 sms_messg->text.s   = buf;
440                 sms_messg->text.len = buf_len;
441                 if ( (ret_code=putsms(sms_messg,mdm))<0)
442                         goto error;
443                 if (sms_report_type!=NO_REPORT)
444                         add_sms_into_report_queue(ret_code,sms_messg,
445                                 p-use_nice*(nr_chunks>1)*SMS_EDGE_PART_LEN,len_array[i]);
446         }
447
448         sms_messg->ref--;
449         /* put back the pointer to the beginning of the message*/
450         sms_messg->text.s = text.s;
451         sms_messg->text.len = text.len;
452         /* remove the sms if nobody points to it */
453         if (!sms_messg->ref){
454                 shm_free(sms_messg);
455         }
456         return 1;
457 error:
458         if (ret_code==-1)
459                 /* bad number */
460                 send_error(sms_messg, sms_messg->to.s, sms_messg->to.len,
461                         ERR_NUMBER_TEXT, ERR_NUMBER_TEXT_LEN);
462         else if (ret_code==-2)
463                 /* bad modem */
464                 send_error(sms_messg, ERR_MODEM_TEXT, ERR_MODEM_TEXT_LEN,
465                         text.s+SMS_HDR_BF_ADDR_LEN+sms_messg->from.len+SMS_HDR_AF_ADDR_LEN,
466                         text.len-SMS_FOOTER_LEN-SMS_HDR_BF_ADDR_LEN-sms_messg->from.len-
467                         SMS_HDR_AF_ADDR_LEN );
468
469         if (!(--(sms_messg->ref)))
470                 shm_free(sms_messg);
471         return -1;
472 }
473
474
475
476
477 int send_sms_as_sip( struct incame_sms *sms )
478 {
479         str  sip_addr;
480         str  sip_body;
481         str  sip_from;
482         int  is_pattern;
483         int  in_address;
484         int  k;
485         char *p;
486
487         /* first we have to parse the body to try to get out
488            the sip destination address;
489            The sms body can to be in the following two formats:
490            1. The entire or part of the sent header still exists - we will
491               pars it and consider the start of the sip message the first
492               character that doesn't match the header!
493            2. The sms body is totally different of the send sms -> search for a
494               sip address inside; everything before it is ignored, only the
495               part following the address being send as sip
496         */
497         in_address = 0;
498         sip_addr.len = 0;
499         sip_body.len = 0;
500         p = sms->ascii;
501
502         /* is our logo (or a part of it) still there? */
503         if (*p==SMS_HDR_BF_ADDR[0]) {
504                 is_pattern = 1;
505                 /* try to match SMS_HDR_BF_ADDR */
506                 k=0;
507                 while( is_pattern && p<sms->ascii+sms->userdatalength
508                 && k<SMS_HDR_BF_ADDR_LEN)
509                         if (*(p++)!=SMS_HDR_BF_ADDR[k++])
510                                 is_pattern = 0;
511                 if (!is_pattern) {
512                         /* first header part is broken -> let's give it a chance
513                            and parse for the first word delimiter */
514                         while(p<sms->ascii+sms->userdatalength && no_sip_addr_begin(*p))
515                                 p++;
516                         p++;
517                         if (p+9>=sms->ascii+sms->userdatalength) {
518                                 LM_ERR("failed to find sip_address start in sms body [%s]!\n",
519                                                 sms->ascii);
520                                 goto error;
521                         }
522                         
523                 }
524                 /* lets get the address */
525                 if (p[0]!='s' || p[1]!='i' || p[2]!='p' || p[3]!=':') {
526                         LM_ERR("wrong sip address format in sms body [%s]!\n",sms->ascii);
527                         goto error;
528                 }
529                 sip_addr.s = p;
530                 /* goes to the end of the address */
531                 while(p<sms->ascii+sms->userdatalength && is_in_sip_addr(*p) )
532                         p++;
533                 if (p>=sms->ascii+sms->userdatalength) {
534                         LM_ERR("failed to find sip address end in sms body [%s]!\n",
535                                         sms->ascii);
536                 }
537                 sip_addr.len = p-sip_addr.s;
538                 LM_DBG("sip address found [%.*s]\n",
539                         sip_addr.len,sip_addr.s);
540                 /* try to match SMS_HDR_AF_ADDR */
541                 k=0;
542                 while( is_pattern && p<sms->ascii+sms->userdatalength
543                 && k<SMS_HDR_AF_ADDR_LEN)
544                         if (*(p++)!=SMS_HDR_AF_ADDR[k++])
545                                 is_pattern = 0;
546         } else {
547                 /* no trace of the pattern sent along with the orig sms*/
548                 do {
549                         if ((p[0]=='s'||p[0]=='S') && (p[1]=='i'||p[1]=='I')
550                         && (p[2]=='p'||p[2]=='P') && p[3]==':') {
551                                 /* we got the address beginning */
552                                 sip_addr.s = p;
553                                 /* goes to the end of the address */
554                                 while(p<sms->ascii+sms->userdatalength && is_in_sip_addr(*p) )
555                                         p++;
556                                 if (p==sms->ascii+sms->userdatalength) {
557                                         LM_ERR("failed to find sip address end in sms body [%s]!\n",
558                                                         sms->ascii);
559                                         goto error;
560                                 }
561                                 sip_addr.len = p-sip_addr.s;
562                         } else {
563                                 /* parse to the next word */
564                                 /*LM_DBG("*** Skipping word len=%d\n",sms->userdatalength);*/
565                                 while(p<sms->ascii+sms->userdatalength&&no_sip_addr_begin(*p)){
566                                         p++;
567                                 }
568                                 p++;
569                                 if (p+9>=sms->ascii+sms->userdatalength) {
570                                 LM_ERR("failed to find sip address start in sms body [%s]!\n",
571                                                 sms->ascii);
572                                         goto error;
573                                 }
574                                 /*LM_DBG("*** Done\n");*/
575                         }
576                 }while (!sip_addr.len);
577         }
578
579         /* the rest of the sms (if any ;-)) is the body! */
580         sip_body.s = p;
581         sip_body.len = sms->ascii + sms->userdatalength - p;
582         /* let's trim out all \n an \r from begining */
583         while ( sip_body.len && sip_body.s
584         && (sip_body.s[0]=='\n' || sip_body.s[0]=='\r') ) {
585                 sip_body.s++;
586                 sip_body.len--;
587         }
588         if (sip_body.len==0) {
589                 LM_WARN("empty body for sms [%s]", sms->ascii);
590                 goto error;
591         }
592         LM_DBG("extracted body is: [%.*s]\n",sip_body.len, sip_body.s);
593
594         /* finally, let's send it as sip message */
595         sip_from.s = sms->sender;
596         sip_from.len = strlen(sms->sender);
597         /* patch the body with date and time */
598         if (sms->userdatalength + CRLF_LEN + 1 /*'('*/ + DATE_LEN
599         + 1 /*','*/ + TIME_LEN + 1 /*')'*/< sizeof(sms->ascii)) {
600                 p = sip_body.s + sip_body.len;
601                 append_str( p, CRLF, CRLF_LEN);
602                 *(p++) = '(';
603                 append_str( p, sms->date, DATE_LEN);
604                 *(p++) = ',';
605                 append_str( p, sms->time, TIME_LEN);
606                 *(p++) = ')';
607                 sip_body.len += CRLF_LEN + DATE_LEN + TIME_LEN + 3;
608         }
609         send_sip_msg_request( &sip_addr, &sip_from, &sip_body);
610
611         return 1;
612 error:
613         return -1;
614 }
615
616
617
618
619 int check_sms_report( struct incame_sms *sms )
620 {
621         struct sms_msg *sms_messg;
622         str *s1, *s2;
623         int old;
624         int res;
625
626         LM_DBG("Report for sms number %d.\n",sms->sms_id);
627         res=relay_report_to_queue( sms->sms_id, sms->sender, sms->ascii[0], &old);
628         if (res==3) { /* error */
629                 /* the sms was confirmed with an error code -> we have to send a
630                 message to the SIP user */
631                 s1 = get_error_str(sms->ascii[0]);
632                 s2 = get_text_from_report_queue(sms->sms_id);
633                 sms_messg = get_sms_from_report_queue(sms->sms_id);
634                 send_error( sms_messg, s1->s, s1->len, s2->s, s2->len);
635         } else if (res==1 && sms->ascii[0]==48 && old!=48) { /* provisional 48 */
636                 /* the sms was provisional confirmed with a 48 code -> was stored
637                 by SMSC -> no further real-time tracing possible */
638                 s2 = get_text_from_report_queue(sms->sms_id);
639                 sms_messg = get_sms_from_report_queue(sms->sms_id);
640                 send_error( sms_messg, STORED_NOTE, STORED_NOTE_LEN, s2->s, s2->len);
641         } else if (res==2 && old==48) {
642                 /* we received OK for a SMS that had received prev. an 48 code.
643                 The note that we send for 48 has to be now clarify */
644                 s2 = get_text_from_report_queue(sms->sms_id);
645                 sms_messg = get_sms_from_report_queue(sms->sms_id);
646                 send_error( sms_messg, OK_MSG, OK_MSG_LEN, s2->s, s2->len);
647         }
648         if (res>1) /* final response */
649                 remove_sms_from_report_queue(sms->sms_id);
650
651         return 1;
652 }
653
654
655
656
657 int check_cds_report( struct modem *mdm, char *cds, int cds_len)
658 {
659         struct incame_sms sms;
660
661         if (cds2sms( &sms, mdm, cds, cds_len)==-1)
662                 return -1;
663         check_sms_report( &sms );
664         return 1;
665 }
666
667
668
669
670 void modem_process(struct modem *mdm)
671 {
672         struct sms_msg    *sms_messg;
673         struct incame_sms sms;
674         struct network *net;
675         int i,k,len;
676         int counter;
677         int dont_wait;
678         int empty_pipe;
679         int cpms_unsuported;
680         int max_mem=0, used_mem=0;
681
682         sms_messg = 0;
683         cpms_unsuported = 0;
684
685         /* let's open/init the modem */
686         LM_DBG("opening modem\n");
687         if (openmodem(mdm)==-1) {
688                 LM_ERR("failed to open modem %s!"
689                         " %s \n",mdm->name,strerror(errno));
690                 return;
691         }
692
693         setmodemparams(mdm);
694         initmodem(mdm,check_cds_report);
695
696         if ( (max_mem=check_memory(mdm,MAX_MEM))==-1 ) {
697                 LM_WARN("CPMS command unsuported! using default values (10,10)\n");
698                 used_mem = max_mem = 10;
699                 cpms_unsuported = 1;
700         }
701         LM_DBG("modem maximum memory is %d\n",max_mem);
702
703         set_gettime_function();
704
705         while(1)
706         {
707                 dont_wait = 0;
708                 for (i=0;i<nr_of_networks && mdm->net_list[i]!=-1;i++)
709                 {
710                         counter = 0;
711                         empty_pipe = 0;
712                         net = &(networks[mdm->net_list[i]]);
713                         /*getting msgs from pipe*/
714                         while( counter<net->max_sms_per_call && !empty_pipe )
715                         {
716                                 /* let's read a sms from pipe */
717                                 len = read(net->pipe_out, &sms_messg,
718                                         sizeof(sms_messg));
719                                 if (len!=sizeof(sms_messg)) {
720                                         if (len>=0)
721                                                 LM_ERR("truncated message read from pipe! "
722                                                                 "-> discarded\n");
723                                         else if (errno==EAGAIN)
724                                                 empty_pipe = 1;
725                                         else
726                                                 LM_ERR("pipe reading failed: %s\n",strerror(errno));
727                                         sleep(1);
728                                         counter++;
729                                         continue;
730                                 }
731                                 (*queued_msgs)--;
732
733                                 /* compute and send the sms */
734                                 LM_DBG("%s processing sms for net %s:"
735                                         " \n\tTo:[%.*s]\n\tBody=<%d>[%.*s]\n",
736                                         mdm->device, net->name,
737                                         sms_messg->to.len,sms_messg->to.s,
738                                         sms_messg->text.len,sms_messg->text.len,sms_messg->text.s);
739                                 send_as_sms( sms_messg , mdm);
740
741                                 counter++;
742                                 /* if I reached the limit -> set not to wait */
743                                 if (counter==net->max_sms_per_call)
744                                         dont_wait = 1;
745                         }/*while*/
746                 }/*for*/
747
748                 /* let's see if we have incoming sms */
749                 if ( !cpms_unsuported )
750                         if ((used_mem = check_memory(mdm,USED_MEM))==-1) {
751                                 LM_ERR("CPMS command failed! cannot get used mem->using 10\n");
752                                 used_mem = 10;
753                         }
754
755                 /* if any, let's get them */
756                 if (used_mem)
757                         LM_DBG("%d new SMS on modem\n",used_mem);
758                         for(i=1,k=1;k<=used_mem && i<=max_mem;i++) {
759                                 if (getsms(&sms,mdm,i)!=-1) {
760                                         k++;
761                                         LM_DBG("SMS Get from location %d\n",i);
762                                         /*for test ;-) ->  to be remove*/
763                                         LM_DBG("SMS RECEIVED:\n\rFrom: %s %s\n\r%.*s %.*s"
764                                                 "\n\r\"%.*s\"\n\r",sms.sender,sms.name,
765                                                 DATE_LEN,sms.date,TIME_LEN,sms.time,
766                                                 sms.userdatalength,sms.ascii);
767                                         if (!sms.is_statusreport)
768                                                 send_sms_as_sip(&sms);
769                                         else 
770                                                 check_sms_report(&sms);
771                                 }
772                         }
773
774                 /* if reports are used, checks for expired records in report queue */
775                 if (sms_report_type!=NO_REPORT)
776                         check_timeout_in_report_queue();
777
778                 /* sleep -> if it's needed */
779                 if (!dont_wait) {
780                                 sleep(mdm->looping_interval);
781                 }
782         }/*while*/
783 }
784
785
786