You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/modules/sms/sms_funcs.c

917 lines
24 KiB

/*
* Copyright (C) 2001-2003 FhG Fokus
*
* This file is part of Kamailio, a free SIP server.
*
* Kamailio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* Kamailio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include "../../dprint.h"
#include "../../ut.h"
#include "../../config.h"
#include "../../globals.h"
#include "../../mem/mem.h"
#include "../../mem/shm_mem.h"
#include "../../parser/parse_uri.h"
#include "../../parser/parse_content.h"
#include "../../parser/parse_from.h"
#include "../../data_lump_rpl.h"
#include "../../cfg/cfg_struct.h"
#include "../../modules/tm/t_hooks.h"
#include "../../modules/tm/uac.h"
#include "sms_funcs.h"
#include "sms_report.h"
#include "libsms_modem.h"
#include "libsms_sms.h"
struct modem modems[MAX_MODEMS];
struct network networks[MAX_NETWORKS];
int net_pipes_in[MAX_NETWORKS];
int nr_of_networks;
int nr_of_modems;
int *queued_msgs;
int use_contact;
struct tm_binds tmb;
#define ERR_NUMBER_TEXT " is an invalid number! Please resend your SMS "\
"using a number in +(country code)(area code)(local number) format. Thanks"\
" for using our service!"
#define ERR_NUMBER_TEXT_LEN (sizeof(ERR_NUMBER_TEXT)-1)
#define ERR_TRUNCATE_TEXT "We are sorry, but your message exceeded our "\
"maximum allowed length. The following part of the message wasn't sent"\
" : "
#define ERR_TRUNCATE_TEXT_LEN (sizeof(ERR_TRUNCATE_TEXT)-1)
#define ERR_MODEM_TEXT "Due to our modem temporary indisponibility, "\
"the following message couldn't be sent : "
#define ERR_MODEM_TEXT_LEN (sizeof(ERR_MODEM_TEXT)-1)
#define STORED_NOTE "NOTE: Your SMS received provisional confirmation"\
" 48 \"Delivery is not yet possible\". The SMS was store on the "\
"SMSCenter for further delivery. Our gateway cannot guarantee "\
"further information regarding your SMS delivery! Your message was: "
#define STORED_NOTE_LEN (sizeof(STORED_NOTE)-1)
#define OK_MSG "Your SMS was finally successfully delivered!"\
" Your message was: "
#define OK_MSG_LEN (sizeof(OK_MSG)-1)
#define CONTENT_TYPE_HDR "Content-Type: text/plain"
#define CONTENT_TYPE_HDR_LEN (sizeof(CONTENT_TYPE_HDR)-1)
#define is_in_sip_addr(_p) \
((_p)!=' ' && (_p)!='\t' && (_p)!='(' && (_p)!='[' && (_p)!='<' \
&& (_p)!='>' && (_p)!=']' && (_p)!=')' && (_p)!='?' && (_p)!='!' \
&& (_p)!=';' && (_p)!=',' && (_p)!='\n' && (_p)!='\r' && (_p)!='=')
#define no_sip_addr_begin(_p) \
( (_p)!=' ' && (_p)!='\t' && (_p)!='-' && (_p)!='=' && (_p)!='\r'\
&& (_p)!='\n' && (_p)!=';' && (_p)!=',' && (_p)!='.' && (_p)!=':')
#if 0
inline int add_contact(struct sip_msg* msg , str* user)
{
struct lump_rpl *lump;
char *buf, *p;
int len;
len = 9 /*"Contact: "*/ + user->len/*user*/ + 1 /*"@"*/
+ domain.len/*host*/ + 6/*"<sip:>"*/ + CRLF_LEN;
buf = pkg_malloc( len );
if(!buf) {
LM_ERR("out of memory! \n");
return -1;
}
p = buf;
append_str( p, "Contact: " , 9);
append_str( p, "<sip:" , 5);
append_str( p, user->s, user->len);
*(p++) = '@';
append_str( p, domain.s, domain.len);
*(p++) = '>';
append_str( p, CRLF, CRLF_LEN);
lump = build_lump_rpl( buf , len , LUMP_RPL_HDR);
if(!lump) {
LM_ERR("unable to build lump_rpl! \n");
pkg_free( buf );
return -1;
}
add_lump_rpl( msg , lump );
pkg_free(buf);
return 1;
}
#endif
int push_on_network(struct sip_msg *msg, int net)
{
str body;
struct sip_uri uri;
struct sms_msg *sms_messg;
struct to_body *from;
char *p;
int len;
int mime;
/* get the message's body
* anyhow we have to call this function, so let's do it at the beginning
* to force the parsing of all the headers - like this we avoid separate
* calls of parse_headers function for FROM, CONTENT_LENGTH, TO hdrs */
body.s = get_body( msg );
if (body.s==0) {
LM_ERR("failed to extract body from msg!\n");
goto error;
}
/* content-length (if present) must be already parsed */
if (!msg->content_length) {
LM_ERR("no Content-Length header found!\n");
goto error;
}
body.len = get_content_length( msg );
/* parse the content-type header */
if ( (mime=parse_content_type_hdr(msg))<1 ) {
LM_ERR("failed to parse Content-Type header\n");
goto error;
}
/* check the content-type value */
if ( mime!=(TYPE_TEXT<<16)+SUBTYPE_PLAIN
&& mime!=(TYPE_MESSAGE<<16)+SUBTYPE_CPIM ) {
LM_ERR("invalid content-type for a message request! type found=%d\n",
mime);
goto error;
}
/* we try to get the user name (phone number) first from the RURI
(in our case means from new_uri or from first_line.u.request.uri);
if it's missing there (like in requests generated by MSN MESSENGER),
we go for "to" header
*/
LM_DBG("string to get user from new_uri\n");
if ( !msg->new_uri.s||parse_uri( msg->new_uri.s,msg->new_uri.len,&uri)
|| !uri.user.len )
{
LM_DBG("string to get user from R_uri\n");
if ( parse_uri( msg->first_line.u.request.uri.s,
msg->first_line.u.request.uri.len ,&uri)||!uri.user.len )
{
LM_DBG("string to get user from To\n");
if ( (!msg->to&&((parse_headers(msg,HDR_TO_F,0)==-1) ||
!msg->to)) ||
parse_uri( get_to(msg)->uri.s, get_to(msg)->uri.len, &uri)==-1
|| !uri.user.len)
{
LM_ERR("unable to extract user name from RURI and To header!\n");
goto error;
}
}
}
/* check the uri.user format = '+(inter code)(number)' */
if (uri.user.len<2 || uri.user.s[0]!='+' || uri.user.s[1]<'1'
|| uri.user.s[1]>'9') {
LM_ERR("user tel number [%.*s] does not respect international format\n"
,uri.user.len,uri.user.s);
goto error;
}
/* parsing from header */
if ( parse_from_header( msg )==-1 ) {
LM_ERR("failed to get FROM header\n");
goto error;
}
from = (struct to_body*)msg->from->parsed;
#if 0
/* adds contact header into reply */
if (add_contact(msg,&(uri.user))==-1) {
LM_ERR("can't build contact for reply\n");
goto error;
}
#endif
/*-------------BUILD AND FILL THE SMS_MSG STRUCTURE --------------------*/
/* computes the amount of memory needed */
len = SMS_HDR_BF_ADDR_LEN + from->uri.len
+ SMS_HDR_AF_ADDR_LEN + body.len + SMS_FOOTER_LEN /*text to send*/
+ from->uri.len /* from */
+ uri.user.len-1 /* to user (without '+') */
+ sizeof(struct sms_msg) ; /* the sms_msg structure */
/* allocs a new sms_msg structure in shared memory */
sms_messg = (struct sms_msg*)shm_malloc(len);
if (!sms_messg) {
LM_ERR("failed to get shm memory!\n");
goto error;
}
p = (char*)sms_messg + sizeof(struct sms_msg);
/* copy "from" into sms struct */
sms_messg->from.len = from->uri.len;
sms_messg->from.s = p;
append_str(p,from->uri.s,from->uri.len);
/* copy "to.user" - we have to strip out the '+' */
sms_messg->to.len = uri.user.len-1;
sms_messg->to.s = p;
append_str(p,uri.user.s+1,sms_messg->to.len);
/* copy (and composing) sms body */
sms_messg->text.len = SMS_HDR_BF_ADDR_LEN + sms_messg->from.len
+ SMS_HDR_AF_ADDR_LEN + body.len+SMS_FOOTER_LEN;
sms_messg->text.s = p;
append_str(p, SMS_HDR_BF_ADDR, SMS_HDR_BF_ADDR_LEN);
append_str(p, sms_messg->from.s, sms_messg->from.len);
append_str(p, SMS_HDR_AF_ADDR, SMS_HDR_AF_ADDR_LEN);
append_str(p, body.s, body.len);
append_str(p, SMS_FOOTER, SMS_FOOTER_LEN);
if (*queued_msgs>MAX_QUEUED_MESSAGES)
goto error;
(*queued_msgs)++;
if (write(net_pipes_in[net], &sms_messg, sizeof(sms_messg))!=
sizeof(sms_messg) )
{
LM_ERR("error when writing for net %d to pipe [%d] : %s\n",
net,net_pipes_in[net],strerror(errno) );
shm_free(sms_messg);
(*queued_msgs)--;
goto error;
}
return 1;
error:
return -1;
}
int send_sip_msg_request(str *to, str *from_user, str *body)
{
str msg_type = STR_STATIC_INIT("MESSAGE");
str from;
str hdrs;
int foo;
char *p;
uac_req_t uac_r;
from.s = hdrs.s = 0;
from.len = hdrs.len = 0;
/* From header */
from.len = 6 /*"<sip:+"*/ + from_user->len/*user*/ + 1/*"@"*/
+ domain.len /*host*/ + 1 /*">"*/ ;
from.s = (char*)pkg_malloc(from.len);
if (!from.s)
goto error;
p=from.s;
append_str(p,"<sip:+",6);
append_str(p,from_user->s,from_user->len);
*(p++)='@';
append_str(p,domain.s,domain.len);
*(p++)='>';
/* hdrs = Contact header + Content-type */
/* length */
hdrs.len = CONTENT_TYPE_HDR_LEN + CRLF_LEN;
if (use_contact)
hdrs.len += 15 /*"Contact: <sip:+"*/ + from_user->len/*user*/ +
1/*"@"*/ + domain.len/*host*/ + 1 /*">"*/ + CRLF_LEN;
hdrs.s = (char*)pkg_malloc(hdrs.len);
if (!hdrs.s)
goto error;
p=hdrs.s;
append_str(p,CONTENT_TYPE_HDR,CONTENT_TYPE_HDR_LEN);
append_str(p,CRLF,CRLF_LEN);
if (use_contact) {
append_str(p,"Contact: <sip:+",15);
append_str(p,from_user->s,from_user->len);
*(p++)='@';
append_str(p,domain.s,domain.len);
append_str(p,">"CRLF,1+CRLF_LEN);
}
/* sending the request */
set_uac_req(&uac_r,
&msg_type, /* request type */
&hdrs, /* Additional headers including CRLF */
body, /* Message body */
0, /* dialog structure */
0, /* callback flags */
0, /* Callback function */
0 /* Callback parameter */
);
foo = tmb.t_request(&uac_r,
0, /* Request-URI */
to, /* To */
&from, /* From */
0 /* next hop */
);
if (from.s) pkg_free(from.s);
if (hdrs.s) pkg_free(hdrs.s);
return foo;
error:
LM_ERR("no free pkg memory!\n");
if (from.s) pkg_free(from.s);
if (hdrs.s) pkg_free(hdrs.s);
return -1;
}
static inline int send_error(struct sms_msg *sms_messg, char *msg1_s, int msg1_len,
char *msg2_s, int msg2_len)
{
str body;
char *p;
int foo;
/* body */
body.len = msg1_len + msg2_len;
body.s = (char*)pkg_malloc(body.len);
if (!body.s)
goto error;
p=body.s;
append_str(p, msg1_s, msg1_len );
append_str(p, msg2_s, msg2_len);
/* sending */
foo = send_sip_msg_request( &(sms_messg->from), &(sms_messg->to), &body);
pkg_free( body.s );
return foo;
error:
LM_ERR("no free pkg memory!\n");
return -1;
}
static inline unsigned int split_text(str *text, unsigned char *lens,int nice)
{
int nr_chunks;
int k,k1,len;
char c;
nr_chunks = 0;
len = 0;
do{
k = MAX_SMS_LENGTH-(nice&&nr_chunks?SMS_EDGE_PART_LEN:0);
if ( len+k<text->len ) {
/* is not the last piece :-( */
if (nice && !nr_chunks) k -= SMS_EDGE_PART_LEN;
if (text->len-len-k<=SMS_FOOTER_LEN+4)
k = (text->len-len)/2;
/* ->looks for a point to split */
k1 = k;
while( k>0 && (c=text->s[len+k-1])!='.' && c!=' ' && c!=';'
&& c!='\r' && c!='\n' && c!='-' && c!='!' && c!='?' && c!='+'
&& c!='=' && c!='\t' && c!='\'')
k--;
if (k<k1/2)
/* wast of space !!!!*/
k=k1;
len += k;
lens[nr_chunks] = k;
}else {
/*last chunk*/
lens[nr_chunks] = text->len-len;
len = text->len;
}
nr_chunks++;
}while (len<text->len);
return nr_chunks;
}
int send_as_sms(struct sms_msg *sms_messg, struct modem *mdm)
{
static char buf[MAX_SMS_LENGTH];
unsigned int buf_len;
unsigned char len_array_1[256], len_array_2[256], *len_array;
unsigned int nr_chunks_1, nr_chunks_2, nr_chunks;
unsigned int use_nice;
str text;
char *p, *q;
int ret_code;
int i;
text.s = sms_messg->text.s;
text.len = sms_messg->text.len;
nr_chunks_1 = split_text( &text, len_array_1, 0);
nr_chunks_2 = split_text( &text, len_array_2, 1);
if (nr_chunks_1==nr_chunks_2) {
len_array = len_array_2;
nr_chunks = nr_chunks_2;
use_nice = 1;
} else {
len_array = len_array_1;
nr_chunks = nr_chunks_1;
use_nice = 0;
}
sms_messg->ref = 1;
for(i=0,p=text.s ; i<nr_chunks&&i<max_sms_parts ; p+=len_array[i++]) {
if (use_nice) {
q = buf;
if (nr_chunks>1 && i) {
append_str(q,SMS_EDGE_PART,SMS_EDGE_PART_LEN);
*(q-2)=nr_chunks+'0';
*(q-4)=i+1+'0';
}
append_str(q,p,len_array[i]);
if (nr_chunks>1 && !i) {
append_str(q,SMS_EDGE_PART,SMS_EDGE_PART_LEN);
*(q-2)=nr_chunks+'0';
*(q-4)=i+1+'0';
}
buf_len = q-buf;
} else {
q = buf;
append_str(q,p,len_array[i]);
buf_len = len_array[i];
}
if (i+1==max_sms_parts && i+1<nr_chunks) {
/* simply override the end of the last allowed part */
buf_len += SMS_TRUNCATED_LEN+SMS_FOOTER_LEN;
if (buf_len>MAX_SMS_LENGTH) buf_len = MAX_SMS_LENGTH;
q = buf + (buf_len-SMS_TRUNCATED_LEN-SMS_FOOTER_LEN);
append_str(q,SMS_TRUNCATED,SMS_TRUNCATED_LEN);
append_str(q,SMS_FOOTER,SMS_FOOTER_LEN);
p += buf_len-SMS_TRUNCATED_LEN-SMS_FOOTER_LEN-SMS_EDGE_PART_LEN;
send_error(sms_messg, ERR_TRUNCATE_TEXT, ERR_TRUNCATE_TEXT_LEN,
p, text.len-(p-text.s)-SMS_FOOTER_LEN);
}
LM_DBG("---%d--<%d><%d>--\n|%.*s|\n", i, len_array[i], buf_len,
(int)buf_len, buf);
sms_messg->text.s = buf;
sms_messg->text.len = buf_len;
if ( (ret_code=putsms(sms_messg,mdm))<0)
goto error;
if (sms_report_type!=NO_REPORT)
add_sms_into_report_queue(ret_code,sms_messg,
p-use_nice*(nr_chunks>1)*SMS_EDGE_PART_LEN,len_array[i]);
}
sms_messg->ref--;
/* put back the pointer to the beginning of the message*/
sms_messg->text.s = text.s;
sms_messg->text.len = text.len;
/* remove the sms if nobody points to it */
if (!sms_messg->ref){
shm_free(sms_messg);
}
return 1;
error:
if (ret_code==-1)
/* bad number */
send_error(sms_messg, sms_messg->to.s, sms_messg->to.len,
ERR_NUMBER_TEXT, ERR_NUMBER_TEXT_LEN);
else if (ret_code==-2)
/* bad modem */
send_error(sms_messg, ERR_MODEM_TEXT, ERR_MODEM_TEXT_LEN,
text.s+SMS_HDR_BF_ADDR_LEN+sms_messg->from.len+SMS_HDR_AF_ADDR_LEN,
text.len-SMS_FOOTER_LEN-SMS_HDR_BF_ADDR_LEN-sms_messg->from.len-
SMS_HDR_AF_ADDR_LEN );
if (!(--(sms_messg->ref)))
shm_free(sms_messg);
return -1;
}
int send_sms_as_sip( struct incame_sms *sms )
{
str sip_addr;
str sip_body;
str sip_from;
int is_pattern;
int k;
char *p;
/* first we have to parse the body to try to get out
the sip destination address;
The sms body can to be in the following two formats:
1. The entire or part of the sent header still exists - we will
pars it and consider the start of the sip message the first
character that doesn't match the header!
2. The sms body is totally different of the send sms -> search for a
sip address inside; everything before it is ignored, only the
part following the address being send as sip
*/
sip_addr.len = 0;
sip_body.len = 0;
p = sms->ascii;
/* is our logo (or a part of it) still there? */
if (*p==SMS_HDR_BF_ADDR[0]) {
is_pattern = 1;
/* try to match SMS_HDR_BF_ADDR */
k=0;
while( is_pattern && p<sms->ascii+sms->userdatalength
&& k<SMS_HDR_BF_ADDR_LEN)
if (*(p++)!=SMS_HDR_BF_ADDR[k++])
is_pattern = 0;
if (!is_pattern) {
/* first header part is broken -> let's give it a chance
and parse for the first word delimiter */
while(p<sms->ascii+sms->userdatalength && no_sip_addr_begin(*p))
p++;
p++;
if (p+9>=sms->ascii+sms->userdatalength) {
LM_ERR("unable to find sip_address start in sms body [%s]!\n",
sms->ascii);
goto error;
}
}
/* lets get the address */
if (p[0]!='s' || p[1]!='i' || p[2]!='p' || p[3]!=':') {
LM_ERR("wrong sip address format in sms body [%s]!\n",sms->ascii);
goto error;
}
sip_addr.s = p;
/* goes to the end of the address */
while(p<sms->ascii+sms->userdatalength && is_in_sip_addr(*p) )
p++;
if (p>=sms->ascii+sms->userdatalength) {
LM_ERR("failed to find sip address end in sms body [%s]!\n",
sms->ascii);
}
sip_addr.len = p-sip_addr.s;
LM_DBG("sip address found [%.*s]\n",
sip_addr.len,sip_addr.s);
/* try to match SMS_HDR_AF_ADDR */
k=0;
while( is_pattern && p<sms->ascii+sms->userdatalength
&& k<SMS_HDR_AF_ADDR_LEN)
if (*(p++)!=SMS_HDR_AF_ADDR[k++])
is_pattern = 0;
} else {
/* no trace of the pattern sent along with the orig sms*/
do {
if ((p[0]=='s'||p[0]=='S') && (p[1]=='i'||p[1]=='I')
&& (p[2]=='p'||p[2]=='P') && p[3]==':') {
/* we got the address beginning */
sip_addr.s = p;
/* goes to the end of the address */
while(p<sms->ascii+sms->userdatalength && is_in_sip_addr(*p) )
p++;
if (p==sms->ascii+sms->userdatalength) {
LM_ERR("failed to find sip address end in sms body [%s]!\n",
sms->ascii);
goto error;
}
sip_addr.len = p-sip_addr.s;
} else {
/* parse to the next word */
/*LM_DBG("*** Skipping word len=%d\n",sms->userdatalength);*/
while(p<sms->ascii+sms->userdatalength&&no_sip_addr_begin(*p)){
p++;
}
p++;
if (p+9>=sms->ascii+sms->userdatalength) {
LM_ERR("unable to find sip address start in sms body [%s]!\n",
sms->ascii);
goto error;
}
/*LM_DBG("*** Done\n");*/
}
}while (!sip_addr.len);
}
/* the rest of the sms (if any ;-)) is the body! */
sip_body.s = p;
sip_body.len = sms->ascii + sms->userdatalength - p;
/* let's trim out all \n an \r from beginning */
while ( sip_body.len && sip_body.s
&& (sip_body.s[0]=='\n' || sip_body.s[0]=='\r') ) {
sip_body.s++;
sip_body.len--;
}
if (sip_body.len==0) {
LM_WARN("empty body for sms [%s]", sms->ascii);
goto error;
}
LM_DBG("extracted body is: [%.*s]\n",sip_body.len, sip_body.s);
/* finally, let's send it as sip message */
sip_from.s = sms->sender;
sip_from.len = strlen(sms->sender);
/* patch the body with date and time */
if (sms->userdatalength + CRLF_LEN + 1 /*'('*/ + DATE_LEN
+ 1 /*','*/ + TIME_LEN + 1 /*')'*/< sizeof(sms->ascii)) {
p = sip_body.s + sip_body.len;
append_str( p, CRLF, CRLF_LEN);
*(p++) = '(';
append_str( p, sms->date, DATE_LEN);
*(p++) = ',';
append_str( p, sms->time, TIME_LEN);
*(p++) = ')';
sip_body.len += CRLF_LEN + DATE_LEN + TIME_LEN + 3;
}
return send_sip_msg_request(&sip_addr, &sip_from, &sip_body);
error:
return -1;
}
int send_sms_as_sip_scan_no(struct incame_sms *sms, char *to)
{
str sip_from;
str sip_to;
str sip_body;
char *p;
/* charge from header */
sip_from.s = sms->sender;
sip_from.len = strlen(sms->sender);
/* charge to header */
sip_to.len = strlen(to);
sip_to.s = to;
/* charge body */
sip_body.len = sms->ascii + sms->userdatalength - sms->ascii;
sip_body.s = sms->ascii;
/* let's trim out all \n an \r from beginning */
while (sip_body.len && sip_body.s &&
(sip_body.s[0] == '\n' || sip_body.s[0] == '\r')) {
sip_body.s++;
sip_body.len--;
}
if (sip_body.len == 0) {
LM_WARN("SMS empty body for sms [%s]\n",sms->ascii);
goto error;
}
/* patch the body with date and time */
if (sms->userdatalength + CRLF_LEN + 1 /*'('*/ + DATE_LEN
+ 1 /*','*/ + TIME_LEN + 1 /*')'*/< sizeof(sms->ascii)) {
p = sip_body.s + sip_body.len;
append_str( p, CRLF, CRLF_LEN);
*(p++) = '(';
append_str( p, sms->date, DATE_LEN);
*(p++) = ',';
append_str( p, sms->time, TIME_LEN);
*(p++) = ')';
sip_body.len += CRLF_LEN + DATE_LEN + TIME_LEN + 3;
}
LM_DBG("SMS from: [%.*s], to: [%.*s], body: [%.*s]\n",
sip_from.len, sip_from.s, sip_to.len, sip_to.s, sip_body.len, sip_body.s);
/* finally, let's send it as sip message */
return send_sip_msg_request(&sip_to, &sip_from, &sip_body);
error:
return -1;
}
int _send_sms_as_sip(struct incame_sms *sms, struct modem *mdm)
{
switch(mdm->scan)
{
case SMS_BODY_SCAN:
return send_sms_as_sip(sms);
case SMS_BODY_SCAN_MIX:
if(send_sms_as_sip(sms) == 1)
return 1;
case SMS_BODY_SCAN_NO:
return send_sms_as_sip_scan_no(sms, mdm->to);
default:
break;
}
/* CASE IMPOSIBLE!!!!, scan assume default value SMS_BODY_SCAN */
LM_ERR("SMS bad config param scan: %d for modem: %s\n",
mdm->scan, mdm->name);
return -1;
}
int check_sms_report( struct incame_sms *sms )
{
struct sms_msg *sms_messg;
str *s1, *s2;
int old;
int res;
LM_DBG("Report for sms number %d.\n",sms->sms_id);
res=relay_report_to_queue( sms->sms_id, sms->sender, sms->ascii[0], &old);
if (res==3) { /* error */
/* the sms was confirmed with an error code -> we have to send a
message to the SIP user */
s1 = get_error_str(sms->ascii[0]);
s2 = get_text_from_report_queue(sms->sms_id);
sms_messg = get_sms_from_report_queue(sms->sms_id);
send_error( sms_messg, s1->s, s1->len, s2->s, s2->len);
} else if (res==1 && sms->ascii[0]==48 && old!=48) { /* provisional 48 */
/* the sms was provisional confirmed with a 48 code -> was stored
by SMSC -> no further real-time tracing possible */
s2 = get_text_from_report_queue(sms->sms_id);
sms_messg = get_sms_from_report_queue(sms->sms_id);
send_error( sms_messg, STORED_NOTE, STORED_NOTE_LEN, s2->s, s2->len);
} else if (res==2 && old==48) {
/* we received OK for a SMS that had received prev. an 48 code.
The note that we send for 48 has to be now clarify */
s2 = get_text_from_report_queue(sms->sms_id);
sms_messg = get_sms_from_report_queue(sms->sms_id);
send_error( sms_messg, OK_MSG, OK_MSG_LEN, s2->s, s2->len);
}
if (res>1) /* final response */
remove_sms_from_report_queue(sms->sms_id);
return 1;
}
int check_cds_report( struct modem *mdm, char *cds, int cds_len)
{
struct incame_sms sms;
if (cds2sms( &sms, mdm, cds, cds_len)==-1)
return -1;
check_sms_report( &sms );
return 1;
}
void modem_process(struct modem *mdm)
{
struct sms_msg *sms_messg;
struct incame_sms sms;
struct network *net;
int i,k,len;
int counter;
int dont_wait;
int empty_pipe;
int cpms_unsuported;
int max_mem=0, used_mem=0;
sms_messg = 0;
cpms_unsuported = 0;
/* let's open/init the modem */
LM_DBG("opening modem\n");
if (openmodem(mdm)==-1) {
LM_ERR("failed to open modem %s! %s \n",
mdm->name,strerror(errno));
return;
}
setmodemparams(mdm);
initmodem(mdm,check_cds_report);
if ( (max_mem=check_memory(mdm,MAX_MEM))==-1 ) {
LM_WARN("CPMS command unsuported! using default values (10,10)\n");
used_mem = max_mem = 10;
cpms_unsuported = 1;
}
LM_DBG("modem maximum memory is %d\n",max_mem);
set_gettime_function();
while(1)
{
/* update the local config */
cfg_update();
dont_wait = 0;
for (i=0;i<nr_of_networks && mdm->net_list[i]!=-1;i++)
{
counter = 0;
empty_pipe = 0;
net = &(networks[mdm->net_list[i]]);
/*getting msgs from pipe*/
while( counter<net->max_sms_per_call && !empty_pipe )
{
/* let's read a sms from pipe */
len = read(net->pipe_out, &sms_messg,
sizeof(sms_messg));
if (len!=sizeof(sms_messg)) {
if (len>=0)
LM_ERR("truncated message read from pipe!"
" -> discarded\n");
else if (errno==EAGAIN)
empty_pipe = 1;
else
LM_ERR("pipe reading failed: %s\n",strerror(errno));
sleep(1);
counter++;
continue;
}
(*queued_msgs)--;
/* compute and send the sms */
LM_DBG("%s processing sms for net %s:"
" \n\tTo:[%.*s]\n\tBody=<%d>[%.*s]\n",
mdm->device, net->name,
sms_messg->to.len,sms_messg->to.s,
sms_messg->text.len,sms_messg->text.len,sms_messg->text.s);
send_as_sms( sms_messg , mdm);
counter++;
/* if I reached the limit -> set not to wait */
if (counter==net->max_sms_per_call)
dont_wait = 1;
}/*while*/
}/*for*/
/* let's see if we have incoming sms */
if ( !cpms_unsuported )
if ((used_mem = check_memory(mdm,USED_MEM))==-1) {
LM_ERR("CPMS command failed! cannot get used mem -> using 10\n");
used_mem = 10;
}
/* if any, let's get them */
if (used_mem)
LM_DBG("%d new SMS on modem\n",used_mem);
for(i=1,k=1;k<=used_mem && i<=max_mem;i++) {
if (getsms(&sms,mdm,i)!=-1) {
k++;
LM_DBG("SMS Get from location %d\n",i);
/*for test ;-) -> to be remove*/
LM_DBG("SMS RECEIVED:\n\rFrom: %s %s\n\r%.*s %.*s"
"\n\r\"%.*s\"\n\r",sms.sender,sms.name,
DATE_LEN,sms.date,TIME_LEN,sms.time,
sms.userdatalength,sms.ascii);
if (!sms.is_statusreport)
_send_sms_as_sip(&sms, mdm);
else
check_sms_report(&sms);
}
}
/* if reports are used, checks for expired records in report queue */
if (sms_report_type!=NO_REPORT)
check_timeout_in_report_queue();
/* sleep -> if it's needed */
if (!dont_wait) {
sleep(mdm->looping_interval);
}
}/*while*/
}