sms_funcs.c

Go to the documentation of this file.
00001 /*
00002  * $Id: sms_funcs.c 4713 2008-08-22 17:48:49Z henningw $
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  * History:
00023  * --------
00024  * 2003-01-23: switched from t_uac to t_uac_dlg, adapted to new way of
00025  *              parsing for Content-Type (bogdan)
00026  * 2003-02-28: protocolization of t_uac_dlg completed (jiri)
00027  * 2003-08-05: adapted to the new parse_content_type_hdr function (bogdan)
00028  * 2003-09-11: updated to new build_lump_rpl() interface (bogdan)
00029  * 2003-09-11: force parsing to hdr when extracting destination user (bogdan)
00030  */
00031 
00032 #include <unistd.h>
00033 #include <errno.h>
00034 #include <stdlib.h>
00035 #include "../../dprint.h"
00036 #include "../../ut.h"
00037 #include "../../config.h"
00038 #include "../../globals.h"
00039 #include "../../mem/mem.h"
00040 #include "../../mem/shm_mem.h"
00041 #include "../../parser/parse_uri.h"
00042 #include "../../parser/parse_content.h"
00043 #include "../../parser/parse_from.h"
00044 #include "../../data_lump_rpl.h"
00045 #include "../tm/t_hooks.h"
00046 #include "../tm/uac.h"
00047 #include "sms_funcs.h"
00048 #include "sms_report.h"
00049 #include "libsms_modem.h"
00050 #include "libsms_sms.h"
00051 
00052 
00053 
00054 
00055 struct modem modems[MAX_MODEMS];
00056 struct network networks[MAX_NETWORKS];
00057 int net_pipes_in[MAX_NETWORKS];
00058 int nr_of_networks;
00059 int nr_of_modems;
00060 int max_sms_parts;
00061 int *queued_msgs;
00062 int use_contact;
00063 int sms_report_type;
00064 struct tm_binds tmb;
00065 
00066 
00067 #define ERR_NUMBER_TEXT " is an invalid number! Please resend your SMS "\
00068    "using a number in +(country code)(area code)(local number) format. Thanks"\
00069    " for using our service!"
00070 #define ERR_NUMBER_TEXT_LEN (sizeof(ERR_NUMBER_TEXT)-1)
00071 
00072 #define ERR_TRUNCATE_TEXT "We are sorry, but your message exceeded our "\
00073    "maximum allowed length. The following part of the message wasn't sent"\
00074    " : "
00075 #define ERR_TRUNCATE_TEXT_LEN (sizeof(ERR_TRUNCATE_TEXT)-1)
00076 
00077 #define ERR_MODEM_TEXT "Due to our modem temporary indisponibility, "\
00078    "the following message couldn't be sent : "
00079 #define ERR_MODEM_TEXT_LEN (sizeof(ERR_MODEM_TEXT)-1)
00080 
00081 #define STORED_NOTE "NOTE: Your SMS received provisional confirmation"\
00082    " 48 \"Delivery is not yet possible\". The SMS was store on the "\
00083    "SMSCenter for further delivery. Our gateway cannot guarantee "\
00084    "further information regarding your SMS delivery! Your message was: "
00085 #define STORED_NOTE_LEN  (sizeof(STORED_NOTE)-1)
00086 
00087 #define OK_MSG "Your SMS was finally successfully delivered!"\
00088    " Your message was: "
00089 #define OK_MSG_LEN  (sizeof(OK_MSG)-1)
00090 
00091 #define CONTENT_TYPE_HDR     "Content-Type: text/plain"
00092 #define CONTENT_TYPE_HDR_LEN (sizeof(CONTENT_TYPE_HDR)-1)
00093 
00094 #define is_in_sip_addr(_p) \
00095    ((_p)!=' ' && (_p)!='\t' && (_p)!='(' && (_p)!='[' && (_p)!='<' \
00096    && (_p)!='>' && (_p)!=']' && (_p)!=')' && (_p)!='?' && (_p)!='!' \
00097    && (_p)!=';' && (_p)!=',' && (_p)!='\n' && (_p)!='\r' && (_p)!='=')
00098 
00099 #define no_sip_addr_begin(_p) \
00100    ( (_p)!=' ' && (_p)!='\t' && (_p)!='-' && (_p)!='=' && (_p)!='\r'\
00101    && (_p)!='\n' && (_p)!=';' && (_p)!=',' && (_p)!='.' && (_p)!=':')
00102 
00103 
00104 
00105 int push_on_network(struct sip_msg *msg, int net)
00106 {
00107    str    body;
00108    struct sip_uri  uri;
00109    struct sms_msg  *sms_messg;
00110    struct to_body  *from;
00111    char   *p;
00112    int    len;
00113    int    mime;
00114 
00115    /* get the message's body
00116     * anyhow we have to call this function, so let's do it at the beginning
00117     * to force the parsing of all the headers - like this we avoid separate
00118     * calls of parse_headers function for FROM, CONTENT_LENGTH, TO hdrs  */
00119    body.s = get_body( msg );
00120    if (body.s==0) {
00121       LM_ERR("failed to extract body from msg!\n");
00122       goto error;
00123    }
00124 
00125    /* content-length (if present) must be already parsed */
00126    if (!msg->content_length) {
00127       LM_ERR("no Content-Length header found!\n");
00128       goto error;
00129    }
00130    body.len = get_content_length( msg );
00131 
00132    /* parse the content-type header */
00133    if ( (mime=parse_content_type_hdr(msg))<1 ) {
00134       LM_ERR("failed to parse Content-Type header\n");
00135       goto error;
00136    }
00137 
00138    /* check the content-type value */
00139    if ( mime!=(TYPE_TEXT<<16)+SUBTYPE_PLAIN
00140    && mime!=(TYPE_MESSAGE<<16)+SUBTYPE_CPIM ) {
00141       LM_ERR("invalid content-type for a message request! type found=%d\n",
00142             mime);
00143       goto error;
00144    }
00145 
00146    /* we try to get the user name (phone number) first from the RURI 
00147       (in our case means from new_uri or from first_line.u.request.uri);
00148       if it's missing there (like in requests generated by MSN MESSENGER),
00149       we go for "to" header
00150    */
00151    LM_DBG("string to get user from new_uri\n");
00152    if ( !msg->new_uri.s||parse_uri( msg->new_uri.s,msg->new_uri.len,&uri)
00153    || !uri.user.len )
00154    {
00155       LM_DBG("string to get user from R_uri\n");
00156       if ( parse_uri( msg->first_line.u.request.uri.s,
00157       msg->first_line.u.request.uri.len ,&uri)||!uri.user.len )
00158       {
00159          LM_DBG("string to get user from To\n");
00160          if ((!msg->to&&((parse_headers(msg,HDR_TO_F,0)==-1)||!msg->to)) ||
00161          parse_uri( get_to(msg)->uri.s, get_to(msg)->uri.len, &uri)<0
00162          || !uri.user.len)
00163          {
00164             LM_ERR("failed to extract user name from RURI"
00165                   " and To header!\n");
00166             goto error;
00167          }
00168       }
00169    }
00170    /* check the uri.user format = '+(inter code)(number)' */
00171    if (uri.user.len<2 || uri.user.s[0]!='+' || uri.user.s[1]<'1'
00172    || uri.user.s[1]>'9') {
00173       LM_ERR("user tel number [%.*s] does not respect international format\n"
00174             ,uri.user.len,uri.user.s);
00175       goto error;
00176    }
00177 
00178    /* parsing from header */
00179    if ( parse_from_header( msg )<0 ) {
00180       LM_ERR("failed get FROM header\n");
00181       goto error;
00182    }
00183    from = (struct to_body*)msg->from->parsed;
00184 
00185    /*-------------BUILD AND FILL THE SMS_MSG STRUCTURE --------------------*/
00186    /* computes the amount of memory needed */
00187    len = SMS_HDR_BF_ADDR_LEN + from->uri.len
00188       + SMS_HDR_AF_ADDR_LEN + body.len + SMS_FOOTER_LEN /*text to send*/
00189       + from->uri.len /* from */
00190       + uri.user.len-1 /* to user (without '+') */
00191       + sizeof(struct sms_msg) ; /* the sms_msg structure */
00192    /* allocs a new sms_msg structure in shared memory */
00193    sms_messg = (struct sms_msg*)shm_malloc(len);
00194    if (!sms_messg) {
00195       LM_ERR("failed get shm memory!\n");
00196       goto error;
00197    }
00198    p = (char*)sms_messg + sizeof(struct sms_msg);
00199 
00200    /* copy "from" into sms struct */
00201    sms_messg->from.len = from->uri.len;
00202    sms_messg->from.s = p;
00203    append_str(p,from->uri.s,from->uri.len);
00204 
00205    /* copy "to.user" - we have to strip out the '+' */
00206    sms_messg->to.len = uri.user.len-1;
00207    sms_messg->to.s = p;
00208    append_str(p,uri.user.s+1,sms_messg->to.len);
00209 
00210    /* copy (and composing) sms body */
00211    sms_messg->text.len = SMS_HDR_BF_ADDR_LEN + sms_messg->from.len
00212       + SMS_HDR_AF_ADDR_LEN + body.len+SMS_FOOTER_LEN;
00213    sms_messg->text.s = p;
00214    append_str(p, SMS_HDR_BF_ADDR, SMS_HDR_BF_ADDR_LEN);
00215    append_str(p, sms_messg->from.s, sms_messg->from.len);
00216    append_str(p, SMS_HDR_AF_ADDR, SMS_HDR_AF_ADDR_LEN);
00217    append_str(p, body.s, body.len);
00218    append_str(p, SMS_FOOTER, SMS_FOOTER_LEN);
00219 
00220    if (*queued_msgs>MAX_QUEUED_MESSAGES)
00221       goto error;
00222    (*queued_msgs)++;
00223 
00224    if (write(net_pipes_in[net], &sms_messg, sizeof(sms_messg))!=
00225    sizeof(sms_messg) )
00226    {
00227       LM_ERR("failed to write for net %d to pipe [%d] : %s\n",
00228             net,net_pipes_in[net],strerror(errno) );
00229       shm_free(sms_messg);
00230       (*queued_msgs)--;
00231       goto error;
00232    }
00233 
00234    return 1;
00235  error:
00236    return -1;
00237 }
00238 
00239 
00240 
00241 
00242 
00243 int send_sip_msg_request(str *to, str *from_user, str *body)
00244 {
00245    str msg_type = { "MESSAGE", 7};
00246    str from;
00247    str hdrs;
00248    int foo;
00249    char *p;
00250 
00251    from.s = hdrs.s = 0;
00252    from.len = hdrs.len = 0;
00253 
00254    /* From header */
00255    from.len = 6 /*"<sip:+"*/ +  from_user->len/*user*/ + 1/*"@"*/
00256       + domain.len /*host*/ + 1 /*">"*/ ;
00257    from.s = (char*)pkg_malloc(from.len);
00258    if (!from.s)
00259       goto error;
00260    p=from.s;
00261    append_str(p,"<sip:+",6);
00262    append_str(p,from_user->s,from_user->len);
00263    *(p++)='@';
00264    append_str(p,domain.s,domain.len);
00265    *(p++)='>';
00266 
00267    /* hdrs = Contact header + Content-type */
00268    /* length */
00269    hdrs.len = CONTENT_TYPE_HDR_LEN + CRLF_LEN;
00270    if (use_contact)
00271       hdrs.len += 15 /*"Contact: <sip:+"*/ + from_user->len/*user*/ +
00272          1/*"@"*/ + domain.len/*host*/ + 1 /*">"*/ + CRLF_LEN;
00273    hdrs.s = (char*)pkg_malloc(hdrs.len);
00274    if (!hdrs.s)
00275       goto error;
00276    p=hdrs.s;
00277    append_str(p,CONTENT_TYPE_HDR,CONTENT_TYPE_HDR_LEN);
00278    append_str(p,CRLF,CRLF_LEN);
00279    if (use_contact) {
00280       append_str(p,"Contact: <sip:+",15);
00281       append_str(p,from_user->s,from_user->len);
00282       *(p++)='@';
00283       append_str(p,domain.s,domain.len);
00284       append_str(p,">"CRLF,1+CRLF_LEN);
00285    }
00286 
00287    /* sending the request */
00288    foo = tmb.t_request( &msg_type,   /* request type */
00289          0,                        /* Request-URI */
00290          to,                       /* To */
00291          &from,                    /* From */
00292          &hdrs,                    /* Additional headers including CRLF */
00293          body,                     /* Message body */
00294          0,                        /* outbound uri */
00295          0,                        /* Callback function */
00296          0                         /* Callback parameter */
00297       );
00298    if (from.s) pkg_free(from.s);
00299    if (hdrs.s) pkg_free(hdrs.s);
00300    return foo;
00301 error:
00302    LM_ERR("no more pkg memory!\n");
00303    if (from.s) pkg_free(from.s);
00304    if (hdrs.s) pkg_free(hdrs.s);
00305    return -1;
00306 }
00307 
00308 
00309 
00310 
00311 inline int send_error(struct sms_msg *sms_messg, char *msg1_s, int msg1_len,
00312                                        char *msg2_s, int msg2_len)
00313 {
00314    str  body;
00315    char *p;
00316    int  foo;
00317 
00318    /* body */
00319    body.len = msg1_len + msg2_len;
00320    body.s = (char*)pkg_malloc(body.len);
00321    if (!body.s)
00322       goto error;
00323    p=body.s;
00324    append_str(p, msg1_s, msg1_len );
00325    append_str(p, msg2_s, msg2_len);
00326 
00327    /* sending */
00328    foo = send_sip_msg_request( &(sms_messg->from), &(sms_messg->to), &body);
00329    pkg_free( body.s );
00330    return foo;
00331 error:
00332    LM_ERR("no more pkg memory!\n");
00333    return -1;
00334 
00335 }
00336 
00337 
00338 
00339 inline unsigned int split_text(str *text, unsigned char *lens,int nice)
00340 {
00341    int  nr_chunks;
00342    int  k,k1,len;
00343    char c;
00344 
00345    nr_chunks = 0;
00346    len = 0;
00347 
00348    do{
00349       k = MAX_SMS_LENGTH-(nice&&nr_chunks?SMS_EDGE_PART_LEN:0);
00350       if ( len+k<text->len ) {
00351          /* is not the last piece :-( */
00352          if (nice && !nr_chunks) k -= SMS_EDGE_PART_LEN;
00353          if (text->len-len-k<=SMS_FOOTER_LEN+4)
00354             k = (text->len-len)/2;
00355          /* ->looks for a point to split */
00356          k1 = k;
00357          while( k>0 && (c=text->s[len+k-1])!='.' && c!=' ' && c!=';'
00358          && c!='\r' && c!='\n' && c!='-' && c!='!' && c!='?' && c!='+'
00359          && c!='=' && c!='\t' && c!='\'')
00360             k--;
00361          if (k<k1/2)
00362             /* wast of space !!!!*/
00363             k=k1;
00364          len += k;
00365          lens[nr_chunks] = k;
00366       }else {
00367          /*last chunk*/
00368          lens[nr_chunks] = text->len-len;
00369          len = text->len;
00370       }
00371       nr_chunks++;
00372    }while (len<text->len);
00373 
00374    return nr_chunks;
00375 }
00376 
00377 
00378 
00379 
00380 int send_as_sms(struct sms_msg *sms_messg, struct modem *mdm)
00381 {
00382    static char   buf[MAX_SMS_LENGTH];
00383    unsigned int  buf_len;
00384    unsigned char len_array_1[256], len_array_2[256], *len_array;
00385    unsigned int  nr_chunks_1,  nr_chunks_2, nr_chunks;
00386    unsigned int  use_nice;
00387    str  text;
00388    char *p, *q;
00389    int  ret_code;
00390    int  i;
00391 
00392    text.s   = sms_messg->text.s;
00393    text.len = sms_messg->text.len;
00394 
00395    nr_chunks_1 = split_text( &text, len_array_1, 0);
00396    nr_chunks_2 = split_text( &text, len_array_2, 1);
00397    if (nr_chunks_1==nr_chunks_2) {
00398       len_array = len_array_2;
00399       nr_chunks = nr_chunks_2;
00400       use_nice = 1;
00401    } else {
00402       len_array = len_array_1;
00403       nr_chunks = nr_chunks_1;
00404       use_nice = 0;
00405    }
00406 
00407    sms_messg->ref = 1;
00408    for(i=0,p=text.s ; i<nr_chunks&&i<max_sms_parts ; p+=len_array[i++]) {
00409       if (use_nice) {
00410          q = buf;
00411          if (nr_chunks>1 && i)  {
00412             append_str(q,SMS_EDGE_PART,SMS_EDGE_PART_LEN);
00413             *(q-2)=nr_chunks+'0';
00414             *(q-4)=i+1+'0';
00415          }
00416          append_str(q,p,len_array[i]);
00417          if (nr_chunks>1 && !i)  {
00418             append_str(q,SMS_EDGE_PART,SMS_EDGE_PART_LEN);
00419             *(q-2)=nr_chunks+'0';
00420             *(q-4)=i+1+'0';
00421          }
00422          buf_len = q-buf;
00423       } else {
00424          q = buf;
00425          append_str(q,p,len_array[i]);
00426          buf_len = len_array[i];
00427       }
00428       if (i+1==max_sms_parts && i+1<nr_chunks) {
00429          /* simply override the end of the last allowed part */
00430          buf_len += SMS_TRUNCATED_LEN+SMS_FOOTER_LEN;
00431          if (buf_len>MAX_SMS_LENGTH) buf_len = MAX_SMS_LENGTH;
00432          q = buf + (buf_len-SMS_TRUNCATED_LEN-SMS_FOOTER_LEN);
00433          append_str(q,SMS_TRUNCATED,SMS_TRUNCATED_LEN);
00434          append_str(q,SMS_FOOTER,SMS_FOOTER_LEN);
00435          p += buf_len-SMS_TRUNCATED_LEN-SMS_FOOTER_LEN-SMS_EDGE_PART_LEN;
00436          send_error(sms_messg, ERR_TRUNCATE_TEXT, ERR_TRUNCATE_TEXT_LEN,
00437             p, text.len-(p-text.s)-SMS_FOOTER_LEN);
00438       }
00439       LM_DBG("---%d--<%d><%d>--\n|%.*s|\n", i, len_array[i], buf_len,
00440                               (int)buf_len, buf);
00441       sms_messg->text.s   = buf;
00442       sms_messg->text.len = buf_len;
00443       if ( (ret_code=putsms(sms_messg,mdm))<0)
00444          goto error;
00445       if (sms_report_type!=NO_REPORT)
00446          add_sms_into_report_queue(ret_code,sms_messg,
00447             p-use_nice*(nr_chunks>1)*SMS_EDGE_PART_LEN,len_array[i]);
00448    }
00449 
00450    sms_messg->ref--;
00451    /* put back the pointer to the beginning of the message*/
00452    sms_messg->text.s = text.s;
00453    sms_messg->text.len = text.len;
00454    /* remove the sms if nobody points to it */
00455    if (!sms_messg->ref){
00456       shm_free(sms_messg);
00457    }
00458    return 1;
00459 error:
00460    if (ret_code==-1)
00461       /* bad number */
00462       send_error(sms_messg, sms_messg->to.s, sms_messg->to.len,
00463          ERR_NUMBER_TEXT, ERR_NUMBER_TEXT_LEN);
00464    else if (ret_code==-2)
00465       /* bad modem */
00466       send_error(sms_messg, ERR_MODEM_TEXT, ERR_MODEM_TEXT_LEN,
00467          text.s+SMS_HDR_BF_ADDR_LEN+sms_messg->from.len+SMS_HDR_AF_ADDR_LEN,
00468          text.len-SMS_FOOTER_LEN-SMS_HDR_BF_ADDR_LEN-sms_messg->from.len-
00469          SMS_HDR_AF_ADDR_LEN );
00470 
00471    if (!(--(sms_messg->ref)))
00472       shm_free(sms_messg);
00473    return -1;
00474 }
00475 
00476 
00477 
00478 
00479 int send_sms_as_sip( struct incame_sms *sms )
00480 {
00481    str  sip_addr;
00482    str  sip_body;
00483    str  sip_from;
00484    int  is_pattern;
00485    int  in_address;
00486    int  k;
00487    char *p;
00488 
00489    /* first we have to parse the body to try to get out
00490       the sip destination address;
00491       The sms body can to be in the following two formats:
00492       1. The entire or part of the sent header still exists - we will
00493          pars it and consider the start of the sip message the first
00494          character that doesn't match the header!
00495       2. The sms body is totally different of the send sms -> search for a
00496          sip address inside; everything before it is ignored, only the
00497          part following the address being send as sip
00498    */
00499    in_address = 0;
00500    sip_addr.len = 0;
00501    sip_body.len = 0;
00502    p = sms->ascii;
00503 
00504    /* is our logo (or a part of it) still there? */
00505    if (*p==SMS_HDR_BF_ADDR[0]) {
00506       is_pattern = 1;
00507       /* try to match SMS_HDR_BF_ADDR */
00508       k=0;
00509       while( is_pattern && p<sms->ascii+sms->userdatalength
00510       && k<SMS_HDR_BF_ADDR_LEN)
00511          if (*(p++)!=SMS_HDR_BF_ADDR[k++])
00512             is_pattern = 0;
00513       if (!is_pattern) {
00514          /* first header part is broken -> let's give it a chance
00515             and parse for the first word delimiter */
00516          while(p<sms->ascii+sms->userdatalength && no_sip_addr_begin(*p))
00517             p++;
00518          p++;
00519          if (p+9>=sms->ascii+sms->userdatalength) {
00520             LM_ERR("failed to find sip_address start in sms body [%s]!\n",
00521                   sms->ascii);
00522             goto error;
00523          }
00524          
00525       }
00526       /* lets get the address */
00527       if (p[0]!='s' || p[1]!='i' || p[2]!='p' || p[3]!=':') {
00528          LM_ERR("wrong sip address format in sms body [%s]!\n",sms->ascii);
00529          goto error;
00530       }
00531       sip_addr.s = p;
00532       /* goes to the end of the address */
00533       while(p<sms->ascii+sms->userdatalength && is_in_sip_addr(*p) )
00534          p++;
00535       if (p>=sms->ascii+sms->userdatalength) {
00536          LM_ERR("failed to find sip address end in sms body [%s]!\n",
00537                sms->ascii);
00538       }
00539       sip_addr.len = p-sip_addr.s;
00540       LM_DBG("sip address found [%.*s]\n",
00541          sip_addr.len,sip_addr.s);
00542       /* try to match SMS_HDR_AF_ADDR */
00543       k=0;
00544       while( is_pattern && p<sms->ascii+sms->userdatalength
00545       && k<SMS_HDR_AF_ADDR_LEN)
00546          if (*(p++)!=SMS_HDR_AF_ADDR[k++])
00547             is_pattern = 0;
00548    } else {
00549       /* no trace of the pattern sent along with the orig sms*/
00550       do {
00551          if ((p[0]=='s'||p[0]=='S') && (p[1]=='i'||p[1]=='I')
00552          && (p[2]=='p'||p[2]=='P') && p[3]==':') {
00553             /* we got the address beginning */
00554             sip_addr.s = p;
00555             /* goes to the end of the address */
00556             while(p<sms->ascii+sms->userdatalength && is_in_sip_addr(*p) )
00557                p++;
00558             if (p==sms->ascii+sms->userdatalength) {
00559                LM_ERR("failed to find sip address end in sms body [%s]!\n",
00560                      sms->ascii);
00561                goto error;
00562             }
00563             sip_addr.len = p-sip_addr.s;
00564          } else {
00565             /* parse to the next word */
00566             /*LM_DBG("*** Skipping word len=%d\n",sms->userdatalength);*/
00567             while(p<sms->ascii+sms->userdatalength&&no_sip_addr_begin(*p)){
00568                p++;
00569             }
00570             p++;
00571             if (p+9>=sms->ascii+sms->userdatalength) {
00572             LM_ERR("failed to find sip address start in sms body [%s]!\n",
00573                   sms->ascii);
00574                goto error;
00575             }
00576             /*LM_DBG("*** Done\n");*/
00577          }
00578       }while (!sip_addr.len);
00579    }
00580 
00581    /* the rest of the sms (if any ;-)) is the body! */
00582    sip_body.s = p;
00583    sip_body.len = sms->ascii + sms->userdatalength - p;
00584    /* let's trim out all \n an \r from begining */
00585    while ( sip_body.len && sip_body.s
00586    && (sip_body.s[0]=='\n' || sip_body.s[0]=='\r') ) {
00587       sip_body.s++;
00588       sip_body.len--;
00589    }
00590    if (sip_body.len==0) {
00591       LM_WARN("empty body for sms [%s]", sms->ascii);
00592       goto error;
00593    }
00594    LM_DBG("extracted body is: [%.*s]\n",sip_body.len, sip_body.s);
00595 
00596    /* finally, let's send it as sip message */
00597    sip_from.s = sms->sender;
00598    sip_from.len = strlen(sms->sender);
00599    /* patch the body with date and time */
00600    if (sms->userdatalength + CRLF_LEN + 1 /*'('*/ + DATE_LEN
00601    + 1 /*','*/ + TIME_LEN + 1 /*')'*/< sizeof(sms->ascii)) {
00602       p = sip_body.s + sip_body.len;
00603       append_str( p, CRLF, CRLF_LEN);
00604       *(p++) = '(';
00605       append_str( p, sms->date, DATE_LEN);
00606       *(p++) = ',';
00607       append_str( p, sms->time, TIME_LEN);
00608       *(p++) = ')';
00609       sip_body.len += CRLF_LEN + DATE_LEN + TIME_LEN + 3;
00610    }
00611    send_sip_msg_request( &sip_addr, &sip_from, &sip_body);
00612 
00613    return 1;
00614 error:
00615    return -1;
00616 }
00617 
00618 
00619 
00620 
00621 int check_sms_report( struct incame_sms *sms )
00622 {
00623    struct sms_msg *sms_messg;
00624    str *s1, *s2;
00625    int old;
00626    int res;
00627 
00628    LM_DBG("Report for sms number %d.\n",sms->sms_id);
00629    res=relay_report_to_queue( sms->sms_id, sms->sender, sms->ascii[0], &old);
00630    if (res==3) { /* error */
00631       /* the sms was confirmed with an error code -> we have to send a
00632       message to the SIP user */
00633       s1 = get_error_str(sms->ascii[0]);
00634       s2 = get_text_from_report_queue(sms->sms_id);
00635       sms_messg = get_sms_from_report_queue(sms->sms_id);
00636       send_error( sms_messg, s1->s, s1->len, s2->s, s2->len);
00637    } else if (res==1 && sms->ascii[0]==48 && old!=48) { /* provisional 48 */
00638       /* the sms was provisional confirmed with a 48 code -> was stored
00639       by SMSC -> no further real-time tracing possible */
00640       s2 = get_text_from_report_queue(sms->sms_id);
00641       sms_messg = get_sms_from_report_queue(sms->sms_id);
00642       send_error( sms_messg, STORED_NOTE, STORED_NOTE_LEN, s2->s, s2->len);
00643    } else if (res==2 && old==48) {
00644       /* we received OK for a SMS that had received prev. an 48 code.
00645       The note that we send for 48 has to be now clarify */
00646       s2 = get_text_from_report_queue(sms->sms_id);
00647       sms_messg = get_sms_from_report_queue(sms->sms_id);
00648       send_error( sms_messg, OK_MSG, OK_MSG_LEN, s2->s, s2->len);
00649    }
00650    if (res>1) /* final response */
00651       remove_sms_from_report_queue(sms->sms_id);
00652 
00653    return 1;
00654 }
00655 
00656 
00657 
00658 
00659 int check_cds_report( struct modem *mdm, char *cds, int cds_len)
00660 {
00661    struct incame_sms sms;
00662 
00663    if (cds2sms( &sms, mdm, cds, cds_len)==-1)
00664       return -1;
00665    check_sms_report( &sms );
00666    return 1;
00667 }
00668 
00669 
00670 
00671 
00672 void modem_process(struct modem *mdm)
00673 {
00674    struct sms_msg    *sms_messg;
00675    struct incame_sms sms;
00676    struct network *net;
00677    int i,k,len;
00678    int counter;
00679    int dont_wait;
00680    int empty_pipe;
00681    int cpms_unsuported;
00682    int max_mem=0, used_mem=0;
00683 
00684    sms_messg = 0;
00685    cpms_unsuported = 0;
00686 
00687    /* let's open/init the modem */
00688    LM_DBG("opening modem\n");
00689    if (openmodem(mdm)==-1) {
00690       LM_ERR("failed to open modem %s!"
00691          " %s \n",mdm->name,strerror(errno));
00692       return;
00693    }
00694 
00695    setmodemparams(mdm);
00696    initmodem(mdm,check_cds_report);
00697 
00698    if ( (max_mem=check_memory(mdm,MAX_MEM))==-1 ) {
00699       LM_WARN("CPMS command unsuported! using default values (10,10)\n");
00700       used_mem = max_mem = 10;
00701       cpms_unsuported = 1;
00702    }
00703    LM_DBG("modem maximum memory is %d\n",max_mem);
00704 
00705    set_gettime_function();
00706 
00707    while(1)
00708    {
00709       dont_wait = 0;
00710       for (i=0;i<nr_of_networks && mdm->net_list[i]!=-1;i++)
00711       {
00712          counter = 0;
00713          empty_pipe = 0;
00714          net = &(networks[mdm->net_list[i]]);
00715          /*getting msgs from pipe*/
00716          while( counter<net->max_sms_per_call && !empty_pipe )
00717          {
00718             /* let's read a sms from pipe */
00719             len = read(net->pipe_out, &sms_messg,
00720                sizeof(sms_messg));
00721             if (len!=sizeof(sms_messg)) {
00722                if (len>=0)
00723                   LM_ERR("truncated message read from pipe! "
00724                         "-> discarded\n");
00725                else if (errno==EAGAIN)
00726                   empty_pipe = 1;
00727                else
00728                   LM_ERR("pipe reading failed: %s\n",strerror(errno));
00729                sleep(1);
00730                counter++;
00731                continue;
00732             }
00733             (*queued_msgs)--;
00734 
00735             /* compute and send the sms */
00736             LM_DBG("%s processing sms for net %s:"
00737                " \n\tTo:[%.*s]\n\tBody=<%d>[%.*s]\n",
00738                mdm->device, net->name,
00739                sms_messg->to.len,sms_messg->to.s,
00740                sms_messg->text.len,sms_messg->text.len,sms_messg->text.s);
00741             send_as_sms( sms_messg , mdm);
00742 
00743             counter++;
00744             /* if I reached the limit -> set not to wait */
00745             if (counter==net->max_sms_per_call)
00746                dont_wait = 1;
00747          }/*while*/
00748       }/*for*/
00749 
00750       /* let's see if we have incoming sms */
00751       if ( !cpms_unsuported )
00752          if ((used_mem = check_memory(mdm,USED_MEM))==-1) {
00753             LM_ERR("CPMS command failed! cannot get used mem->using 10\n");
00754             used_mem = 10;
00755          }
00756 
00757       /* if any, let's get them */
00758       if (used_mem)
00759          LM_DBG("%d new SMS on modem\n",used_mem);
00760          for(i=1,k=1;k<=used_mem && i<=max_mem;i++) {
00761             if (getsms(&sms,mdm,i)!=-1) {
00762                k++;
00763                LM_DBG("SMS Get from location %d\n",i);
00764                /*for test ;-) ->  to be remove*/
00765                LM_DBG("SMS RECEIVED:\n\rFrom: %s %s\n\r%.*s %.*s"
00766                   "\n\r\"%.*s\"\n\r",sms.sender,sms.name,
00767                   DATE_LEN,sms.date,TIME_LEN,sms.time,
00768                   sms.userdatalength,sms.ascii);
00769                if (!sms.is_statusreport)
00770                   send_sms_as_sip(&sms);
00771                else 
00772                   check_sms_report(&sms);
00773             }
00774          }
00775 
00776       /* if reports are used, checks for expired records in report queue */
00777       if (sms_report_type!=NO_REPORT)
00778          check_timeout_in_report_queue();
00779 
00780       /* sleep -> if it's needed */
00781       if (!dont_wait) {
00782             sleep(mdm->looping_interval);
00783       }
00784    }/*while*/
00785 }
00786 
00787 
00788 

Generated on Thu May 24 12:00:30 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6