00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <stdio.h>
00034 #include <string.h>
00035 #include <stdlib.h>
00036 #include <unistd.h>
00037 #include <fcntl.h>
00038
00039 #include "../../sr_module.h"
00040 #include "../../error.h"
00041 #include "../../dprint.h"
00042 #include "../../ut.h"
00043 #include "../../globals.h"
00044 #include "../../mem/mem.h"
00045 #include "../../mem/shm_mem.h"
00046 #include "../../socket_info.h"
00047 #include "../tm/tm_load.h"
00048 #include "sms_funcs.h"
00049 #include "sms_report.h"
00050 #include "libsms_modem.h"
00051
00052
00053 MODULE_VERSION
00054
00055
00056 static int sms_init(void);
00057 static int sms_exit(void);
00058 static int w_sms_send_msg(struct sip_msg*, char*, char* );
00059 static int w_sms_send_msg_to_net(struct sip_msg*, char*, char*);
00060 static int fixup_sms_send_msg_to_net(void** param, int param_no);
00061 static void sms_process(int);
00062
00063
00064
00065
00066 char *networks_config = 0;
00067 char *modems_config = 0;
00068 char *links_config = 0;
00069 char *default_net_str = 0;
00070 char *domain_str = 0;
00071
00072
00073 int default_net = 0;
00074 int max_sms_parts = MAX_SMS_PARTS;
00075 str domain;
00076 int *queued_msgs = 0;
00077 int use_contact = 0;
00078 int sms_report_type = NO_REPORT;
00079 struct tm_binds tmb;
00080
00081
00082 static proc_export_t sms_procs[] = {
00083 {"SMS receiver", 0, 0, sms_process, 0 },
00084 {0,0,0,0,0}
00085 };
00086
00087
00088 static cmd_export_t cmds[]={
00089 {"sms_send_msg_to_net", (cmd_function)w_sms_send_msg_to_net, 1,
00090 fixup_sms_send_msg_to_net, 0, REQUEST_ROUTE},
00091 {"sms_send_msg", (cmd_function)w_sms_send_msg, 0,
00092 0, 0, REQUEST_ROUTE},
00093 {0,0,0,0,0,0}
00094 };
00095
00096
00097 static param_export_t params[]={
00098 {"networks", STR_PARAM, &networks_config },
00099 {"modems", STR_PARAM, &modems_config },
00100 {"links", STR_PARAM, &links_config },
00101 {"default_net", STR_PARAM, &default_net_str },
00102 {"max_sms_parts", INT_PARAM, &max_sms_parts },
00103 {"domain", STR_PARAM, &domain_str },
00104 {"use_contact", INT_PARAM, &use_contact },
00105 {"sms_report_type", INT_PARAM, &sms_report_type },
00106 {0,0,0}
00107 };
00108
00109
00110 struct module_exports exports= {
00111 "sms",
00112 DEFAULT_DLFLAGS,
00113 cmds,
00114 params,
00115 0,
00116 0,
00117 0,
00118 sms_procs,
00119 sms_init,
00120 0,
00121 (destroy_function) sms_exit,
00122 0
00123 };
00124
00125
00126
00127
00128 static int fixup_sms_send_msg_to_net(void** param, int param_no)
00129 {
00130 long net_nr,i;
00131
00132 if (param_no==1) {
00133 for(net_nr=-1,i=0;i<nr_of_networks&&net_nr==-1;i++)
00134 if (!strcasecmp(networks[i].name,*param))
00135 net_nr = i;
00136 if (net_nr==-1) {
00137 LM_ERR("etwork \"%s\" not found in net list!\n",(char*)*param);
00138 return E_UNSPEC;
00139 } else {
00140 pkg_free(*param);
00141 *param=(void*)net_nr;
00142 return 0;
00143 }
00144 }
00145 return 0;
00146 }
00147
00148
00149
00150
00151
00152 #define eat_spaces(_p) \
00153 while( *(_p)==' ' || *(_p)=='\t' ){\
00154 (_p)++;}
00155
00156
00157
00158
00159 int set_modem_arg(struct modem *mdm, char *arg, char *arg_end)
00160 {
00161 int err, foo;
00162
00163 if (*(arg+1)!='=') {
00164 LM_ERR("invalid parameter syntax near [=]\n");
00165 goto error;
00166 }
00167 switch (*arg)
00168 {
00169 case 'd':
00170 memcpy(mdm->device,arg+2,arg_end-arg-2);
00171 mdm->device[arg_end-arg-2] = 0;
00172 break;
00173 case 'p':
00174 memcpy(mdm->pin,arg+2,arg_end-arg-2);
00175 mdm->pin[arg_end-arg-2] = 0;
00176 break;
00177 case 'm':
00178 if (!strncasecmp(arg+2,"OLD",3)
00179 && arg_end-arg-2==3) {
00180 mdm->mode = MODE_OLD;
00181 } else if (!strncasecmp(arg+2,"DIGICOM",7)
00182 && arg_end-arg-2==7) {
00183 mdm->mode = MODE_DIGICOM;
00184 } else if (!strncasecmp(arg+2,"ASCII",5)
00185 && arg_end-arg-2==5) {
00186 mdm->mode = MODE_ASCII;
00187 } else if (!strncasecmp(arg+2,"NEW",3)
00188 && arg_end-arg-2==3) {
00189 mdm->mode = MODE_NEW;
00190 } else {
00191 LM_ERR("invalid value \"%.*s\" for param [m]\n",
00192 (int)(arg_end-arg-2),arg+2);
00193 goto error;
00194 }
00195 break;
00196 case 'c':
00197 memcpy(mdm->smsc,arg+2,arg_end-arg-2);
00198 mdm->smsc[arg_end-arg-2] = 0;
00199 break;
00200 case 'r':
00201 foo=str2s(arg+2,arg_end-arg-2,&err);
00202 if (err) {
00203 LM_ERR("failed to convert [r] arg to integer!\n");
00204 goto error;
00205 }
00206 mdm->retry = foo;
00207 break;
00208 case 'l':
00209 foo=str2s(arg+2,arg_end-arg-2,&err);
00210 if (err) {
00211 LM_ERR("failed to convert [l] arg to integer!\n");
00212 goto error;
00213 }
00214 mdm->looping_interval = foo;
00215 break;
00216 case 'b':
00217 foo=str2s(arg+2,arg_end-arg-2,&err);
00218 if (err) {
00219 LM_ERR("failed to convert [b] arg to integer!\n");
00220 goto error;
00221 }
00222 switch (foo) {
00223 case 300: foo=B300; break;
00224 case 1200: foo=B1200; break;
00225 case 2400: foo=B2400; break;
00226 case 9600: foo=B9600; break;
00227 case 19200: foo=B19200; break;
00228 case 38400: foo=B38400; break;
00229 case 57600: foo=B57600; break;
00230 default:
00231 LM_ERR("unsupported value %d for [b] arg!\n",foo);
00232 goto error;
00233 }
00234 mdm->baudrate = foo;
00235 break;
00236 default:
00237 LM_ERR("unknown param name [%c]\n",*arg);
00238 goto error;
00239 }
00240
00241 return 1;
00242 error:
00243 return -1;
00244 }
00245
00246
00247
00248
00249 int set_network_arg(struct network *net, char *arg, char *arg_end)
00250 {
00251 int err,foo;
00252
00253 if (*(arg+1)!='=') {
00254 LM_ERR("invalid parameter syntax near [=]\n");
00255 goto error;
00256 }
00257 switch (*arg)
00258 {
00259 case 'm':
00260 foo=str2s(arg+2,arg_end-arg-2,&err);
00261 if (err) {
00262 LM_ERR("cannot convert [m] arg to integer!\n");
00263 goto error;
00264 }
00265 net->max_sms_per_call = foo;
00266 break;
00267 default:
00268 LM_ERR("unknown param name [%c]\n",*arg);
00269 goto error;
00270 }
00271
00272 return 1;
00273 error:
00274 return -1;
00275 }
00276
00277
00278
00279
00280 int parse_config_lines(void)
00281 {
00282 char *p,*start;
00283 int i, k, step;
00284 int mdm_nr, net_nr;
00285
00286 nr_of_networks = 0;
00287 nr_of_modems = 0;
00288
00289 step = 1;
00290
00291 if ( (p = modems_config)==0) {
00292 LM_ERR("param \"modems\" not found\n");
00293 goto error;
00294 }
00295 while (*p)
00296 {
00297 eat_spaces(p);
00298
00299 start = p;
00300 while (*p!=' ' && *p!='\t' && *p!='[' && *p!=0)
00301 p++;
00302 if ( p==start || *p==0 )
00303 goto parse_error;
00304 memcpy(modems[nr_of_modems].name, start, p-start);
00305 modems[nr_of_modems].name[p-start] = 0;
00306 modems[nr_of_modems].smsc[0] = 0;
00307 modems[nr_of_modems].device[0] = 0;
00308 modems[nr_of_modems].pin[0] = 0;
00309 modems[nr_of_modems].mode = MODE_NEW;
00310 modems[nr_of_modems].retry = 4;
00311 modems[nr_of_modems].looping_interval = 20;
00312 modems[nr_of_modems].baudrate = B9600;
00313 memset(modems[nr_of_modems].net_list,0XFF,
00314 sizeof(modems[nr_of_modems].net_list) );
00315
00316 eat_spaces(p);
00317 if (*p!='[')
00318 goto parse_error;
00319 p++;
00320 while (*p!=']')
00321 {
00322 eat_spaces(p);
00323 start = p;
00324 while(*p!=' ' && *p!='\t' && *p!=']' && *p!=';' && *p!=0)
00325 p++;
00326 if ( p==start || *p==0 )
00327 goto parse_error;
00328 if (set_modem_arg( &(modems[nr_of_modems]), start, p)==-1)
00329 goto error;
00330 eat_spaces(p);
00331 if (*p==';') {
00332 p++;
00333 eat_spaces(p);
00334 }
00335 }
00336 if (*p!=']')
00337 goto parse_error;
00338 p++;
00339
00340 if (modems[nr_of_modems].device[0]==0) {
00341 LM_ERR("modem %s has no device associated\n",
00342 modems[nr_of_modems].name);
00343 goto error;
00344 }
00345 if (modems[nr_of_modems].smsc[0]==0) {
00346 LM_WARN("modem %s has no sms center associated -> using"
00347 " the default one from modem\n",modems[nr_of_modems].name);
00348 }
00349 nr_of_modems++;
00350 eat_spaces(p);
00351 if (*p==';') {
00352 p++;
00353 eat_spaces(p);
00354 }
00355 }
00356 if (nr_of_modems==0)
00357 {
00358 LM_ERR("failed to parse config modems - no modem found!\n");
00359 goto error;
00360 }
00361
00362 step++;
00363
00364 if ( (p = networks_config)==0) {
00365 LM_ERR("param \"networks\" not found\n");
00366 goto error;
00367 }
00368 while (*p)
00369 {
00370 eat_spaces(p);
00371
00372 start = p;
00373 while (*p!=' ' && *p!='\t' && *p!='[' && *p!=0)
00374 p++;
00375 if ( p==start || *p==0 )
00376 goto parse_error;
00377 memcpy(networks[nr_of_networks].name, start, p-start);
00378 networks[nr_of_networks].name[p-start] = 0;
00379 networks[nr_of_networks].max_sms_per_call = 10;
00380
00381 eat_spaces(p);
00382 if (*p!='[')
00383 goto parse_error;
00384 p++;
00385 while (*p!=']')
00386 {
00387 eat_spaces(p);
00388 start = p;
00389 while(*p!=' ' && *p!='\t' && *p!=']' && *p!=';' && *p!=0)
00390 p++;
00391 if ( p==start || *p==0 )
00392 goto parse_error;
00393 if (set_network_arg( &(networks[nr_of_networks]), start, p)==-1)
00394 goto error;
00395 eat_spaces(p);
00396 if (*p==';') {
00397 p++;
00398 eat_spaces(p);
00399 }
00400 }
00401 if (*p!=']')
00402 goto parse_error;
00403 p++;
00404
00405 nr_of_networks++;
00406 eat_spaces(p);
00407 if (*p==';')
00408 p++;
00409 eat_spaces(p);
00410 }
00411 if (nr_of_networks==0)
00412 {
00413 LM_ERR("no network found!\n");
00414 goto error;
00415 }
00416
00417 step++;
00418
00419 if ( (p = links_config)==0) {
00420 LM_ERR("param \"links\" not found\n");
00421 goto error;
00422 }
00423 while (*p)
00424 {
00425 eat_spaces(p);
00426
00427 start = p;
00428 while (*p!=' ' && *p!='\t' && *p!='[' && *p!=0)
00429 p++;
00430 if ( p==start || *p==0 )
00431 goto parse_error;
00432
00433 for(mdm_nr=-1,i=0;i<nr_of_modems && mdm_nr==-1;i++)
00434 if (!strncasecmp(modems[i].name,start,p-start)&&
00435 modems[i].name[p-start]==0)
00436 mdm_nr = i;
00437 if (mdm_nr==-1) {
00438 LM_ERR("unknown modem %.*s \n,",(int)(p-start), start);
00439 goto error;
00440 }
00441
00442 eat_spaces(p);
00443 if (*p!='[')
00444 goto parse_error;
00445 p++;
00446 k=0;
00447 while (*p!=']')
00448 {
00449 eat_spaces(p);
00450 start = p;
00451 while(*p!=' ' && *p!='\t' && *p!=']' && *p!=';' && *p!=0)
00452 p++;
00453 if ( p==start || *p==0 )
00454 goto parse_error;
00455
00456 for(net_nr=-1,i=0;i<nr_of_networks&&net_nr==-1;i++)
00457 if (!strncasecmp(networks[i].name,start,p-start)
00458 && networks[i].name[p-start]==0)
00459 net_nr = i;
00460 if (net_nr==-1) {
00461 LM_ERR("associated net <%.*s> not found in net list\n",
00462 (int)(p-start), start);
00463 goto error;
00464 }
00465 LM_DBG("linking net \"%s\" to modem \"%s\" on pos %d.\n",
00466 networks[net_nr].name,modems[mdm_nr].name,k);
00467 modems[mdm_nr].net_list[k++]=net_nr;
00468 eat_spaces(p);
00469 if (*p==';') {
00470 p++;
00471 eat_spaces(p);
00472 }
00473 }
00474 if (*p!=']')
00475 goto parse_error;
00476 p++;
00477
00478 eat_spaces(p);
00479 if (*p==';') {
00480 p++;
00481 eat_spaces(p);
00482 }
00483 }
00484
00485
00486 if (default_net_str) {
00487 for(net_nr=-1,i=0;i<nr_of_networks&&net_nr==-1;i++)
00488 if (!strcasecmp(networks[i].name,default_net_str))
00489 net_nr = i;
00490 if (net_nr==-1) {
00491 LM_ERR("network \"%s\" not found in net list!\n",default_net_str);
00492 goto error;
00493 }
00494 default_net = net_nr;
00495 }
00496
00497 return 0;
00498 parse_error:
00499 LM_ERR("SMS %s config: parse error before chr %d [%.*s]\n",
00500 (step==1)?"modems":(step==2?"networks":"links"),
00501 (int)(p - ((step==1)?modems_config:
00502 (step==2?networks_config:links_config))),
00503 (*p==0)?4:1,(*p==0)?"NULL":p );
00504
00505 error:
00506 return -1;
00507 }
00508
00509
00510
00511
00512 int global_init(void)
00513 {
00514 int i, net_pipe[2], foo;
00515 char *p;
00516 struct socket_info* si;
00517
00518
00519 if (load_tm_api(&tmb)!=0) {
00520 LM_ERR("failed to load TM API\n");
00521 goto error;
00522 }
00523
00524
00525 if (domain_str) {
00526 domain.s = domain_str;
00527 domain.len = strlen(domain_str);
00528 } else {
00529 si=get_first_socket();
00530 if (si==0){
00531 LM_CRIT("null listen socket list\n");
00532 goto error;
00533 }
00534
00535 i = (si->port_no_str.len && si->port_no!=5060);
00536 domain.len = si->name.len + i*(si->port_no_str.len+1);
00537 domain.s = (char*)pkg_malloc(domain.len);
00538 if (!domain.s) {
00539 LM_ERR("no more pkg memory!\n");
00540 goto error;
00541 }
00542 p = domain.s;
00543 memcpy(p,si->name.s,si->name.len);
00544 p += si->name.len;
00545 if (i) {
00546 *p=':'; p++;
00547 memcpy(p,si->port_no_str.s, si->port_no_str.len);
00548 p += si->port_no_str.len;
00549 }
00550 }
00551
00552
00553 for(i=0;i<nr_of_networks;i++)
00554 {
00555
00556 if (pipe(net_pipe)==-1) {
00557 LM_ERR("failed create pipe!\n");
00558 goto error;
00559 }
00560 networks[i].pipe_out = net_pipe[0];
00561 net_pipes_in[i] = net_pipe[1];
00562
00563 if ((foo=fcntl(net_pipe[0],F_GETFL,0))<0) {
00564 LM_ERR("failed to get flag for pipe - fcntl\n");
00565 goto error;
00566 }
00567 foo |= O_NONBLOCK;
00568 if (fcntl(net_pipe[0],F_SETFL,foo)<0) {
00569 LM_ERR("failed to set flag for pipe"
00570 " - fcntl\n");
00571 goto error;
00572 }
00573 }
00574
00575
00576 if (sms_report_type!=NO_REPORT && !init_report_queue()) {
00577 LM_ERR("no more share memory!\n");
00578 goto error;
00579 }
00580
00581
00582 queued_msgs = (int*)shm_malloc(sizeof(int));
00583 if (!queued_msgs) {
00584 LM_ERR("no more share memory!\n");
00585 goto error;
00586 }
00587 *queued_msgs = 0;
00588
00589 return 1;
00590 error:
00591 return -1;
00592 }
00593
00594
00595
00596 void sms_process(int rank)
00597 {
00598 modem_process(&(modems[rank]));
00599 exit(-1);
00600 }
00601
00602
00603
00604 static int sms_init(void)
00605 {
00606 if (parse_config_lines()==-1)
00607 return -1;
00608 if (global_init()==-1)
00609 return -1;
00610
00611 sms_procs[0].no = nr_of_modems;
00612 return 0;
00613 }
00614
00615
00616
00617
00618 static int sms_exit(void)
00619 {
00620 if ((!domain_str) && (domain.s))
00621 pkg_free(domain.s);
00622
00623 if (queued_msgs)
00624 shm_free(queued_msgs);
00625
00626 if (sms_report_type!=NO_REPORT)
00627 destroy_report_queue();
00628
00629 return 0;
00630 }
00631
00632
00633
00634
00635 static int w_sms_send_msg(struct sip_msg *msg, char *foo, char *bar)
00636 {
00637 return push_on_network(msg, default_net);
00638 }
00639
00640
00641
00642
00643 static int w_sms_send_msg_to_net(struct sip_msg *msg, char *net_nr, char *foo)
00644 {
00645 return push_on_network(msg,(unsigned int)(unsigned long)net_nr);
00646 }
00647