rtimer_mod.c

00001 
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <stdlib.h>
00026 #include <sys/types.h>
00027 #include <sys/ipc.h>
00028 #include <unistd.h>
00029 #include <fcntl.h>
00030 
00031 #include "../../sr_module.h"
00032 #include "../../timer.h"
00033 #include "../../dprint.h"
00034 #include "../../route.h"
00035 #include "../../receive.h"
00036 #include "../../action.h"
00037 #include "../../socket_info.h"
00038 #include "../../dset.h"
00039 #include "../../pt.h"
00040 #include "../../timer_proc.h"
00041 #include "../../script_cb.h"
00042 #include "../../parser/parse_param.h"
00043 #include "../../lib/kcore/faked_msg.h"
00044 
00045 
00046 MODULE_VERSION
00047 
00048 typedef struct _stm_route {
00049         str timer;
00050         unsigned int route;
00051         struct _stm_route *next;
00052 } stm_route_t;
00053 
00054 typedef struct _stm_timer {
00055         str name;
00056         unsigned int mode;
00057         unsigned int flags;
00058         unsigned int interval;
00059         stm_route_t *rt;
00060         struct _stm_timer *next;
00061 } stm_timer_t;
00062 
00063 #define RTIMER_INTERVAL_USEC    (1<<0)
00064 
00065 stm_timer_t *_stm_list = NULL;
00066 
00068 static int mod_init(void);
00069 static int child_init(int);
00070 
00071 int stm_t_param(modparam_t type, void* val);
00072 int stm_e_param(modparam_t type, void* val);
00073 void stm_timer_exec(unsigned int ticks, void *param);
00074 
00075 
00076 static param_export_t params[]={
00077         {"timer",             STR_PARAM|USE_FUNC_PARAM, (void*)stm_t_param},
00078         {"exec",              STR_PARAM|USE_FUNC_PARAM, (void*)stm_e_param},
00079         {0,0,0}
00080 };
00081 
00082 
00084 struct module_exports exports= {
00085         "rtimer",
00086         DEFAULT_DLFLAGS, /* dlopen flags */
00087         0,
00088         params,
00089         0,          /* exported statistics */
00090         0,          /* exported MI functions */
00091         0,          /* exported pseudo-variables */
00092         0,          /* extra processes */
00093         mod_init,   /* module initialization function */
00094         0,
00095         0,
00096         child_init  /* per-child init function */
00097 };
00098 
00099 
00103 static int mod_init(void)
00104 {
00105         stm_timer_t *it;
00106         if(_stm_list==NULL)
00107                 return 0;
00108 
00109         /* init faked sip msg */
00110         if(faked_msg_init()<0)
00111         {
00112                 LM_ERR("failed to init timer local sip msg\n");
00113                 return -1;
00114         }
00115 
00116         /* register timers */
00117         it = _stm_list;
00118         while(it)
00119         {
00120                 if(it->mode==0)
00121                 {
00122                         if(register_timer(stm_timer_exec, (void*)it, it->interval)<0)
00123                         {
00124                                 LM_ERR("failed to register timer function\n");
00125                                 return -1;
00126                         }
00127                 } else {
00128                         register_basic_timers(1);
00129                 }
00130                 it = it->next;
00131         }
00132 
00133         return 0;
00134 }
00135 
00136 static int child_init(int rank)
00137 {
00138         stm_timer_t *it;
00139         if(_stm_list==NULL)
00140                 return 0;
00141 
00142         if (rank!=PROC_MAIN)
00143                 return 0;
00144 
00145         it = _stm_list;
00146         while(it)
00147         {
00148                 if(it->mode!=0)
00149                 {
00150                         if(it->flags & RTIMER_INTERVAL_USEC)
00151                         {
00152                                 if(fork_basic_utimer(PROC_TIMER, "RTIMER USEC EXEC", 1 /*socks flag*/,
00153                                                                 stm_timer_exec, (void*)it, it->interval
00154                                                                 /*usec*/)<0) {
00155                                         LM_ERR("failed to start utimer routine as process\n");
00156                                         return -1; /* error */
00157                                 }
00158                         } else {
00159                                 if(fork_basic_timer(PROC_TIMER, "RTIMER SEC EXEC", 1 /*socks flag*/,
00160                                                                 stm_timer_exec, (void*)it, it->interval
00161                                                                 /*sec*/)<0) {
00162                                         LM_ERR("failed to start timer routine as process\n");
00163                                         return -1; /* error */
00164                                 }
00165                         }
00166                 }
00167                 it = it->next;
00168         }
00169 
00170         return 0;
00171 }
00172 
00173 void stm_timer_exec(unsigned int ticks, void *param)
00174 {
00175         stm_timer_t *it;
00176         stm_route_t *rt;
00177         sip_msg_t *fmsg;
00178 
00179         if(param==NULL)
00180                 return;
00181         it = (stm_timer_t*)param;
00182         if(it->rt==NULL)
00183                 return;
00184 
00185         for(rt=it->rt; rt; rt=rt->next)
00186         {
00187                 fmsg = faked_msg_next();
00188                 if (exec_pre_script_cb(fmsg, REQUEST_CB_TYPE)==0 )
00189                         continue; /* drop the request */
00190                 set_route_type(REQUEST_ROUTE);
00191                 run_top_route(main_rt.rlist[rt->route], fmsg, 0);
00192                 exec_post_script_cb(fmsg, REQUEST_CB_TYPE);
00193         }
00194 }
00195 
00196 int stm_t_param(modparam_t type, void *val)
00197 {
00198         param_t* params_list = NULL;
00199         param_hooks_t phooks;
00200         param_t *pit=NULL;
00201         stm_timer_t tmp;
00202         stm_timer_t *nt;
00203         str s;
00204 
00205         if(val==NULL)
00206                 return -1;
00207         s.s = (char*)val;
00208         s.len = strlen(s.s);
00209         if(s.s[s.len-1]==';')
00210                 s.len--;
00211         if (parse_params(&s, CLASS_ANY, &phooks, &params_list)<0)
00212                 return -1;
00213         memset(&tmp, 0, sizeof(stm_timer_t));
00214         for (pit = params_list; pit; pit=pit->next)
00215         {
00216                 if (pit->name.len==4
00217                                 && strncasecmp(pit->name.s, "name", 4)==0) {
00218                         tmp.name = pit->body;
00219                 } else if(pit->name.len==4
00220                                 && strncasecmp(pit->name.s, "mode", 4)==0) {
00221                         if(tmp.mode==0)
00222                                 str2int(&pit->body, &tmp.mode);
00223                 }  else if(pit->name.len==8
00224                                 && strncasecmp(pit->name.s, "interval", 8)==0) {
00225                         if(pit->body.s[pit->body.len-1]=='u'
00226                                         || pit->body.s[pit->body.len-1]=='U') {
00227                                 pit->body.len--;
00228                                 tmp.flags |= RTIMER_INTERVAL_USEC;
00229                                 tmp.mode = 1;
00230                         }
00231                         str2int(&pit->body, &tmp.interval);
00232                 }
00233         }
00234         if(tmp.name.s==NULL)
00235         {
00236                 LM_ERR("invalid timer name\n");
00237                 free_params(params_list);
00238                 return -1;
00239         }
00240         /* check for same timer */
00241         nt = _stm_list;
00242         while(nt) {
00243                 if(nt->name.len==tmp.name.len
00244                                 && strncasecmp(nt->name.s, tmp.name.s, tmp.name.len)==0)
00245                         break;
00246                 nt = nt->next;
00247         }
00248         if(nt!=NULL)
00249         {
00250                 LM_ERR("duplicate timer with same name: %.*s\n",
00251                                 tmp.name.len, tmp.name.s);
00252                 free_params(params_list);
00253                 return -1;
00254         }
00255         if(tmp.interval==0)
00256                 tmp.interval = 120;
00257 
00258         nt = (stm_timer_t*)pkg_malloc(sizeof(stm_timer_t));
00259         if(nt==0)
00260         {
00261                 LM_ERR("no more pkg memory\n");
00262                 free_params(params_list);
00263                 return -1;
00264         }
00265         memcpy(nt, &tmp, sizeof(stm_timer_t));
00266         nt->next = _stm_list;
00267         _stm_list = nt;
00268         free_params(params_list);
00269         return 0;
00270 }
00271 
00272 int stm_e_param(modparam_t type, void *val)
00273 {
00274         param_t* params_list = NULL;
00275         param_hooks_t phooks;
00276         param_t *pit=NULL;
00277         stm_route_t tmp;
00278         stm_route_t *rt;
00279         stm_timer_t *nt;
00280         str s;
00281         char c;
00282 
00283         if(val==NULL)
00284                 return -1;
00285         s.s = (char*)val;
00286         s.len = strlen(s.s);
00287         if(s.s[s.len-1]==';')
00288                 s.len--;
00289         if (parse_params(&s, CLASS_ANY, &phooks, &params_list)<0)
00290                 return -1;
00291         memset(&tmp, 0, sizeof(stm_route_t));
00292         for (pit = params_list; pit; pit=pit->next)
00293         {
00294                 if (pit->name.len==5
00295                                 && strncasecmp(pit->name.s, "timer", 5)==0) {
00296                         tmp.timer = pit->body;
00297                 } else if(pit->name.len==5
00298                                 && strncasecmp(pit->name.s, "route", 5)==0) {
00299                         s = pit->body;
00300                 }
00301         }
00302         if(tmp.timer.s==NULL)
00303         {
00304                 LM_ERR("invalid timer name\n");
00305                 free_params(params_list);
00306                 return -1;
00307         }
00308         /* get the timer */
00309         nt = _stm_list;
00310         while(nt) {
00311                 if(nt->name.len==tmp.timer.len
00312                                 && strncasecmp(nt->name.s, tmp.timer.s, tmp.timer.len)==0)
00313                         break;
00314                 nt = nt->next;
00315         }
00316         if(nt==NULL)
00317         {
00318                 LM_ERR("timer not found - name: %.*s\n",
00319                                 tmp.timer.len, tmp.timer.s);
00320                 free_params(params_list);
00321                 return -1;
00322         }
00323         c = s.s[s.len];
00324         s.s[s.len] = '\0';
00325         tmp.route = route_get(&main_rt, s.s);
00326         s.s[s.len] = c;
00327         if(tmp.route == -1)
00328         {
00329                 LM_ERR("invalid route: %.*s\n",
00330                                 s.len, s.s);
00331                 free_params(params_list);
00332                 return -1;
00333         }
00334 
00335         rt = (stm_route_t*)pkg_malloc(sizeof(stm_route_t));
00336         if(rt==0)
00337         {
00338                 LM_ERR("no more pkg memory\n");
00339                 free_params(params_list);
00340                 return -1;
00341         }
00342         memcpy(rt, &tmp, sizeof(stm_route_t));
00343         rt->next = nt->rt;
00344         nt->rt = rt;
00345         free_params(params_list);
00346         return 0;
00347 }
00348