4 * Copyright (C) 2001-2003 FhG Fokus
6 * This file is part of Kamailio, a free SIP server.
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
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.
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
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)
35 #include "../../dprint.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"
56 struct modem modems[MAX_MODEMS];
57 struct network networks[MAX_NETWORKS];
58 int net_pipes_in[MAX_NETWORKS];
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)
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"\
75 #define ERR_TRUNCATE_TEXT_LEN (sizeof(ERR_TRUNCATE_TEXT)-1)
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)
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)
87 #define OK_MSG "Your SMS was finally successfully delivered!"\
89 #define OK_MSG_LEN (sizeof(OK_MSG)-1)
91 #define CONTENT_TYPE_HDR "Content-Type: text/plain"
92 #define CONTENT_TYPE_HDR_LEN (sizeof(CONTENT_TYPE_HDR)-1)
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)!='=')
99 #define no_sip_addr_begin(_p) \
100 ( (_p)!=' ' && (_p)!='\t' && (_p)!='-' && (_p)!='=' && (_p)!='\r'\
101 && (_p)!='\n' && (_p)!=';' && (_p)!=',' && (_p)!='.' && (_p)!=':')
105 int push_on_network(struct sip_msg *msg, int net)
109 struct sms_msg *sms_messg;
110 struct to_body *from;
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 );
121 LM_ERR("failed to extract body from msg!\n");
125 /* content-length (if present) must be already parsed */
126 if (!msg->content_length) {
127 LM_ERR("no Content-Length header found!\n");
130 body.len = get_content_length( msg );
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");
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",
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
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)
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 )
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
164 LM_ERR("failed to extract user name from RURI"
165 " and To header!\n");
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);
178 /* parsing from header */
179 if ( parse_from_header( msg )<0 ) {
180 LM_ERR("failed get FROM header\n");
183 from = (struct to_body*)msg->from->parsed;
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);
195 LM_ERR("failed get shm memory!\n");
198 p = (char*)sms_messg + sizeof(struct sms_msg);
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);
205 /* copy "to.user" - we have to strip out the '+' */
206 sms_messg->to.len = uri.user.len-1;
208 append_str(p,uri.user.s+1,sms_messg->to.len);
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);
220 if (*queued_msgs>MAX_QUEUED_MESSAGES)
224 if (write(net_pipes_in[net], &sms_messg, sizeof(sms_messg))!=
227 LM_ERR("failed to write for net %d to pipe [%d] : %s\n",
228 net,net_pipes_in[net],strerror(errno) );
243 int send_sip_msg_request(str *to, str *from_user, str *body)
245 str msg_type = { "MESSAGE", 7};
253 from.len = hdrs.len = 0;
256 from.len = 6 /*"<sip:+"*/ + from_user->len/*user*/ + 1/*"@"*/
257 + domain.len /*host*/ + 1 /*">"*/ ;
258 from.s = (char*)pkg_malloc(from.len);
262 append_str(p,"<sip:+",6);
263 append_str(p,from_user->s,from_user->len);
265 append_str(p,domain.s,domain.len);
268 /* hdrs = Contact header + Content-type */
270 hdrs.len = CONTENT_TYPE_HDR_LEN + CRLF_LEN;
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);
278 append_str(p,CONTENT_TYPE_HDR,CONTENT_TYPE_HDR_LEN);
279 append_str(p,CRLF,CRLF_LEN);
281 append_str(p,"Contact: <sip:+",15);
282 append_str(p,from_user->s,from_user->len);
284 append_str(p,domain.s,domain.len);
285 append_str(p,">"CRLF,1+CRLF_LEN);
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,
296 if (from.s) pkg_free(from.s);
297 if (hdrs.s) pkg_free(hdrs.s);
300 LM_ERR("no more pkg memory!\n");
301 if (from.s) pkg_free(from.s);
302 if (hdrs.s) pkg_free(hdrs.s);
309 inline int send_error(struct sms_msg *sms_messg, char *msg1_s, int msg1_len,
310 char *msg2_s, int msg2_len)
317 body.len = msg1_len + msg2_len;
318 body.s = (char*)pkg_malloc(body.len);
322 append_str(p, msg1_s, msg1_len );
323 append_str(p, msg2_s, msg2_len);
326 foo = send_sip_msg_request( &(sms_messg->from), &(sms_messg->to), &body);
330 LM_ERR("no more pkg memory!\n");
337 inline unsigned int split_text(str *text, unsigned char *lens,int nice)
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 */
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!='\'')
360 /* wast of space !!!!*/
366 lens[nr_chunks] = text->len-len;
370 }while (len<text->len);
378 int send_as_sms(struct sms_msg *sms_messg, struct modem *mdm)
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;
390 text.s = sms_messg->text.s;
391 text.len = sms_messg->text.len;
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;
400 len_array = len_array_1;
401 nr_chunks = nr_chunks_1;
406 for(i=0,p=text.s ; i<nr_chunks&&i<max_sms_parts ; p+=len_array[i++]) {
409 if (nr_chunks>1 && i) {
410 append_str(q,SMS_EDGE_PART,SMS_EDGE_PART_LEN);
411 *(q-2)=nr_chunks+'0';
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';
423 append_str(q,p,len_array[i]);
424 buf_len = len_array[i];
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);
437 LM_DBG("---%d--<%d><%d>--\n|%.*s|\n", i, len_array[i], buf_len,
439 sms_messg->text.s = buf;
440 sms_messg->text.len = buf_len;
441 if ( (ret_code=putsms(sms_messg,mdm))<0)
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]);
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){
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)
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 );
469 if (!(--(sms_messg->ref)))
477 int send_sms_as_sip( struct incame_sms *sms )
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
502 /* is our logo (or a part of it) still there? */
503 if (*p==SMS_HDR_BF_ADDR[0]) {
505 /* try to match SMS_HDR_BF_ADDR */
507 while( is_pattern && p<sms->ascii+sms->userdatalength
508 && k<SMS_HDR_BF_ADDR_LEN)
509 if (*(p++)!=SMS_HDR_BF_ADDR[k++])
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))
517 if (p+9>=sms->ascii+sms->userdatalength) {
518 LM_ERR("failed to find sip_address start in sms body [%s]!\n",
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);
530 /* goes to the end of the address */
531 while(p<sms->ascii+sms->userdatalength && is_in_sip_addr(*p) )
533 if (p>=sms->ascii+sms->userdatalength) {
534 LM_ERR("failed to find sip address end in sms body [%s]!\n",
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 */
542 while( is_pattern && p<sms->ascii+sms->userdatalength
543 && k<SMS_HDR_AF_ADDR_LEN)
544 if (*(p++)!=SMS_HDR_AF_ADDR[k++])
547 /* no trace of the pattern sent along with the orig sms*/
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 */
553 /* goes to the end of the address */
554 while(p<sms->ascii+sms->userdatalength && is_in_sip_addr(*p) )
556 if (p==sms->ascii+sms->userdatalength) {
557 LM_ERR("failed to find sip address end in sms body [%s]!\n",
561 sip_addr.len = p-sip_addr.s;
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)){
569 if (p+9>=sms->ascii+sms->userdatalength) {
570 LM_ERR("failed to find sip address start in sms body [%s]!\n",
574 /*LM_DBG("*** Done\n");*/
576 }while (!sip_addr.len);
579 /* the rest of the sms (if any ;-)) is the body! */
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') ) {
588 if (sip_body.len==0) {
589 LM_WARN("empty body for sms [%s]", sms->ascii);
592 LM_DBG("extracted body is: [%.*s]\n",sip_body.len, sip_body.s);
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);
603 append_str( p, sms->date, DATE_LEN);
605 append_str( p, sms->time, TIME_LEN);
607 sip_body.len += CRLF_LEN + DATE_LEN + TIME_LEN + 3;
609 send_sip_msg_request( &sip_addr, &sip_from, &sip_body);
619 int check_sms_report( struct incame_sms *sms )
621 struct sms_msg *sms_messg;
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);
648 if (res>1) /* final response */
649 remove_sms_from_report_queue(sms->sms_id);
657 int check_cds_report( struct modem *mdm, char *cds, int cds_len)
659 struct incame_sms sms;
661 if (cds2sms( &sms, mdm, cds, cds_len)==-1)
663 check_sms_report( &sms );
670 void modem_process(struct modem *mdm)
672 struct sms_msg *sms_messg;
673 struct incame_sms sms;
680 int max_mem=0, used_mem=0;
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));
694 initmodem(mdm,check_cds_report);
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;
701 LM_DBG("modem maximum memory is %d\n",max_mem);
703 set_gettime_function();
708 for (i=0;i<nr_of_networks && mdm->net_list[i]!=-1;i++)
712 net = &(networks[mdm->net_list[i]]);
713 /*getting msgs from pipe*/
714 while( counter<net->max_sms_per_call && !empty_pipe )
716 /* let's read a sms from pipe */
717 len = read(net->pipe_out, &sms_messg,
719 if (len!=sizeof(sms_messg)) {
721 LM_ERR("truncated message read from pipe! "
723 else if (errno==EAGAIN)
726 LM_ERR("pipe reading failed: %s\n",strerror(errno));
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);
742 /* if I reached the limit -> set not to wait */
743 if (counter==net->max_sms_per_call)
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");
755 /* if any, let's get them */
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) {
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);
770 check_sms_report(&sms);
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();
778 /* sleep -> if it's needed */
780 sleep(mdm->looping_interval);