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