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 #include <string.h>
00030 #include <stdlib.h>
00031 #include <stdio.h>
00032 #include <ctype.h>
00033 #include "../../timer.h"
00034 #include "../../timer_ticks.h"
00035 #include "../../route.h"
00036 #include "../../sr_module.h"
00037 #include "../../mem/mem.h"
00038 #include "../../mem/shm_mem.h"
00039 #include "../../str.h"
00040 #include "../../error.h"
00041 #include "../../config.h"
00042 #include "../../trim.h"
00043 #include "../../select.h"
00044 #include "../../ut.h"
00045 #include "../../select_buf.h"
00046
00047 #include "../../receive.h"
00048 #include "../../ip_addr.h"
00049
00050 #include "../../receive.h"
00051 #include "../../globals.h"
00052 #include "../../route.h"
00053 #include "../../parser/msg_parser.h"
00054 #include "../../action.h"
00055 #include "../../script_cb.h"
00056 #include "../../dset.h"
00057 #include "../../usr_avp.h"
00058
00059
00060 MODULE_VERSION
00061
00062 #define MODULE_NAME "timer"
00063
00064 struct timer_action {
00065 char *timer_name;
00066 int route_no;
00067 int interval;
00068 int enable_on_start;
00069 int disable_itself;
00070 unsigned short flags;
00071 struct timer_ln *link;
00072
00073 struct timer_action* next;
00074 };
00075
00076
00077 static struct timer_action* timer_actions = 0;
00078 static struct timer_action* pkg_timer_actions = 0;
00079 static struct receive_info rcv_info;
00080 static struct timer_action* timer_executed = 0;
00081
00082 #define eat_spaces(_p) \
00083 while( *(_p)==' ' || *(_p)=='\t' ){\
00084 (_p)++;}
00085
00086 #define eat_alphanum(_p) \
00087 while ( (*(_p) >= 'a' && *(_p) <= 'z') || (*(_p) >= 'A' && *(_p) <= 'Z') || (*(_p) >= '0' && *(_p) <= '9') || (*(_p) == '_') ) {\
00088 (_p)++;\
00089 }
00090
00091 static struct timer_action* find_action_by_name(struct timer_action* timer_actions, char *name, int len) {
00092 struct timer_action *a;
00093 if (len == -1) len = strlen(name);
00094 for (a=timer_actions; a; a = a->next) {
00095 if (a->timer_name && strlen(a->timer_name)==len && strncmp(name, a->timer_name, len) == 0)
00096 return a;
00097 }
00098 return NULL;
00099 }
00100
00101 static int sel_root(str* res, select_t* s, struct sip_msg* msg) {
00102 return 0;
00103 }
00104
00105 static int sel_timer(str* res, select_t* s, struct sip_msg* msg) {
00106 struct timer_action* a;
00107 if (!msg) {
00108 a = find_action_by_name(timer_actions , s->params[2].v.s.s, s->params[2].v.s.len);
00109 if (!a) {
00110 ERR(MODULE_NAME": timer_enable_fixup: timer '%.*s' not declared\n", s->params[2].v.s.len, s->params[2].v.s.s);
00111 return E_CFG;
00112 }
00113 s->params[2].v.p = a;
00114 }
00115 return 0;
00116 }
00117
00118 static int sel_enabled(str* res, select_t* s, struct sip_msg* msg) {
00119 static char buf[2] = "01";
00120 if (!msg) return sel_timer(res, s, msg);
00121 res->len = 1;
00122 res->s = &buf[(((struct timer_action*) s->params[2].v.p)->link->flags & F_TIMER_ACTIVE) != 0];
00123 return 0;
00124 }
00125
00126 static int sel_executed(str* res, select_t* s, struct sip_msg* msg) {
00127 if (!timer_executed) return 1;
00128 res->s = timer_executed->timer_name;
00129 res->len = strlen(res->s);
00130 return 0;
00131 }
00132
00133 select_row_t sel_declaration[] = {
00134 { NULL, SEL_PARAM_STR, STR_STATIC_INIT(MODULE_NAME), sel_root, SEL_PARAM_EXPECTED},
00135 { sel_root, SEL_PARAM_STR, STR_STATIC_INIT("timer"), sel_timer, SEL_PARAM_EXPECTED|CONSUME_NEXT_STR|FIXUP_CALL},
00136 { sel_timer, SEL_PARAM_STR, STR_STATIC_INIT("enabled"), sel_enabled, 0},
00137 { sel_root, SEL_PARAM_STR, STR_STATIC_INIT("executed"), sel_executed, 0},
00138
00139 { NULL, SEL_PARAM_STR, STR_NULL, NULL, 0}
00140 };
00141
00142 static unsigned int timer_msg_no = 0;
00143
00144 static ticks_t timer_handler(ticks_t ticks, struct timer_ln* tl, void* data) {
00145
00146 #define MSG "GET /timer HTTP/0.9\n\n"
00147 struct sip_msg* msg;
00148 struct timer_action *a;
00149 struct run_act_ctx ra_ctx;
00150
00151 a = data;
00152 if (!a->disable_itself) {
00153
00154 DEBUG(MODULE_NAME": handler: called at %d ticks, timer: '%s', pid:%d\n", ticks, a->timer_name, getpid());
00155
00156 if (a->route_no >= main_rt.idx) {
00157 BUG(MODULE_NAME": invalid routing table number #%d of %d\n", a->route_no, main_rt.idx);
00158 goto err2;
00159 }
00160 if (!main_rt.rlist[a->route_no]) {
00161 WARN(MODULE_NAME": route not declared (hash:%d)\n", a->route_no);
00162 goto err2;
00163 }
00164 msg=pkg_malloc(sizeof(struct sip_msg));
00165 if (msg==0) {
00166 ERR(MODULE_NAME": handler: no mem for sip_msg\n");
00167 goto err2;
00168 }
00169 timer_msg_no++;
00170 memset(msg, 0, sizeof(struct sip_msg));
00171
00172 msg->buf=MSG;
00173 msg->len=sizeof(MSG)-1;
00174
00175 msg->rcv= rcv_info;
00176 msg->id=timer_msg_no;
00177 msg->set_global_address=default_global_address;
00178 msg->set_global_port=default_global_port;
00179
00180 if (parse_msg(msg->buf, msg->len, msg)!=0){
00181 ERR(MODULE_NAME": handler: parse_msg failed\n");
00182 goto err;
00183 }
00184
00185 clear_branches();
00186 reset_static_buffer();
00187 if (exec_pre_script_cb(msg, REQUEST_CB_TYPE)==0 )
00188 goto end;
00189
00190 timer_executed = a;
00191 init_run_actions_ctx(&ra_ctx);
00192 run_actions(&ra_ctx, main_rt.rlist[a->route_no], msg);
00193 timer_executed = 0;
00194
00195 exec_post_script_cb(msg, REQUEST_CB_TYPE);
00196 end:
00197 reset_avps();
00198 DEBUG(MODULE_NAME": handler: cleaning up\n");
00199 err:
00200 free_sip_msg(msg);
00201 pkg_free(msg);
00202 err2: ;
00203 }
00204
00205 if (a->disable_itself) {
00206
00207 timer_allow_del();
00208 timer_del(a->link);
00209 timer_reinit(a->link);
00210 a->disable_itself = 0;
00211
00212 return 0;
00213 }
00214 else
00215 return (ticks_t)(-1);
00216 }
00217
00218 static int timer_enable_fixup(void** param, int param_no) {
00219 struct timer_action* a;
00220 int n;
00221 switch (param_no) {
00222 case 1:
00223 a = find_action_by_name(timer_actions , (char*) *param, -1);
00224 if (!a) {
00225 ERR(MODULE_NAME": timer_enable_fixup: timer '%s' not declared\n", (char*) *param);
00226 return E_CFG;
00227 }
00228 *param = a;
00229 break;
00230 case 2:
00231
00232
00233 n=atoi((char *)*param);
00234 *param = (void*)(long)(n != 0);
00235 break;
00236 default: ;
00237 }
00238 return 0;
00239 }
00240
00241 static int timer_enable_func(struct sip_msg* m, char* timer_act, char* enable) {
00242 struct timer_action* a;
00243 int en;
00244 a = (void*) timer_act;
00245 en = (int)(long) enable;
00246
00247
00248
00249
00250 if ((a->link->flags & F_TIMER_ACTIVE) == 0) {
00251 if (en) {
00252 timer_reinit(a->link);
00253 timer_add(a->link, MS_TO_TICKS(a->interval));
00254 a->disable_itself = 0;
00255 }
00256 }
00257 else {
00258 if (en && a->disable_itself) {
00259 a->disable_itself = 0;
00260 }
00261 else if (!en) {
00262 a->disable_itself++;
00263 }
00264 }
00265
00266 return 1;
00267 }
00268
00269 static int get_next_part(char** s, str* part, char delim) {
00270 char *c, *c2;
00271 c = c2 = *s;
00272 eat_spaces(c);
00273 while (*c2!=delim && *c2!=0) c2++;
00274
00275 if (*c2) {
00276 *s = c2+1;
00277 }
00278 else {
00279 *s = c2;
00280 }
00281 eat_spaces(*s);
00282 c2--;
00283
00284 while ( c2 >= c && ((*c2 == ' ')||(*c2 == '\t')) ) c2--;
00285 part->s = c;
00286 part->len = c2-c+1;
00287 return part->len;
00288 }
00289
00290
00291 static int declare_timer(modparam_t type, char* param) {
00292 int n;
00293 unsigned int route_no, interval, enabled, flags;
00294 struct timer_action *pa;
00295 char *p, *save_p, c, *timer_name;
00296 str s;
00297
00298 timer_name = 0;
00299 save_p = p = param;
00300 eat_alphanum(p);
00301 if (*p != '=' || p == save_p) goto err;
00302 *p = '\0';
00303 timer_name = save_p;
00304 p++;
00305 if (find_action_by_name(pkg_timer_actions, timer_name, -1) != NULL) {
00306 ERR(MODULE_NAME": declare_timer: timer '%s' already exists\n", timer_name);
00307 return E_CFG;
00308 }
00309
00310 save_p = p;
00311 if (!get_next_part(&p, &s, ',')) goto err;
00312
00313 c = s.s[s.len];
00314 s.s[s.len] = '\0';
00315 n = route_get(&main_rt, s.s);
00316 s.s[s.len] = c;
00317 if (n == -1) goto err;
00318 route_no = n;
00319
00320 save_p = p;
00321 if (!get_next_part(&p, &s, ',')) goto err;
00322 if (str2int(&s, &interval) < 0) goto err;
00323
00324 save_p = p;
00325 flags = 0;
00326 if (get_next_part(&p, &s, ',')) {
00327 if (s.len == 4 && strncasecmp(s.s, "FAST", 4)==0)
00328 flags = F_TIMER_FAST;
00329 else if (s.len == 4 && strncasecmp(s.s, "SLOW", 4)==0)
00330 ;
00331 else goto err;
00332 }
00333
00334 save_p = p;
00335 enabled = 0;
00336 if (get_next_part(&p, &s, ',')) {
00337 if (s.len == 6 && strncasecmp(s.s, "ENABLE", 6)==0)
00338 enabled = 1;
00339 else goto err;
00340 }
00341
00342
00343 pa = pkg_malloc(sizeof(*pa));
00344 if (!pa) {
00345 ERR(MODULE_NAME": cannot allocate timer data\n");
00346 return E_OUT_OF_MEM;
00347 }
00348 memset(pa, 0, sizeof(*pa));
00349 pa->timer_name = timer_name;
00350 pa->route_no = route_no;
00351 pa->interval = interval;
00352 pa->enable_on_start = enabled;
00353 pa->flags = flags;
00354 pa->next = pkg_timer_actions;
00355 pkg_timer_actions = pa;
00356
00357 return 0;
00358 err:
00359 ERR(MODULE_NAME": declare_timer: timer_name: '%s', error near '%s'\n", timer_name, save_p);
00360 return E_CFG;
00361 }
00362
00363 static int mod_init() {
00364 struct timer_action *a, **pa;
00365
00366 DEBUG(MODULE_NAME": init: initializing, pid=%d\n", getpid());
00367
00368
00369 for (pa=&timer_actions; pkg_timer_actions; pa=&(*pa)->next) {
00370 a = pkg_timer_actions;
00371 *pa = shm_malloc(sizeof(**pa));
00372 if (!*pa) {
00373 ERR(MODULE_NAME": cannot allocate timer data\n");
00374 return E_OUT_OF_MEM;
00375 }
00376 memcpy(*pa, a, sizeof(**pa));
00377 (*pa)->next = 0;
00378 pkg_timer_actions = a->next;
00379 pkg_free(a);
00380 }
00381
00382 for (a=timer_actions; a; a=a->next) {
00383 a->link = timer_alloc();
00384 if (!a->link) {
00385 ERR(MODULE_NAME": init: cannot allocate timer\n");
00386 return E_OUT_OF_MEM;
00387 }
00388 timer_init(a->link, timer_handler, a, a->flags);
00389 if (!a->link) {
00390 ERR(MODULE_NAME": init: cannot initialize timer\n");
00391 return E_CFG;
00392 }
00393 }
00394
00395 memset(&rcv_info, 0, sizeof(rcv_info));
00396 register_select_table(sel_declaration);
00397 return 0;
00398 }
00399
00400 static int child_init(int rank) {
00401 struct timer_action* a;
00402
00403 if (rank!=PROC_TIMER) return 0;
00404 for (a=timer_actions; a; a=a->next) {
00405 if (a->enable_on_start) {
00406 timer_add(a->link, MS_TO_TICKS(a->interval));
00407 }
00408 }
00409 return 0;
00410 }
00411
00412 static void destroy_mod(void) {
00413 struct timer_action* a;
00414 DEBUG(MODULE_NAME": destroy: destroying, pid=%d\n", getpid());
00415 while (timer_actions) {
00416 a = timer_actions;
00417 if (a->link) {
00418 timer_del(a->link);
00419 timer_free(a->link);
00420 }
00421 timer_actions = a->next;
00422 shm_free(a);
00423 }
00424 }
00425
00426
00427
00428
00429 static cmd_export_t cmds[] = {
00430 {MODULE_NAME"_enable", timer_enable_func, 2, timer_enable_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
00431 {0, 0, 0, 0, 0}
00432 };
00433
00434
00435
00436
00437 static param_export_t params[] = {
00438 {"declare_timer", PARAM_STRING|PARAM_USE_FUNC, (void*) declare_timer},
00439 {0, 0, 0}
00440 };
00441
00442
00443 struct module_exports exports = {
00444 MODULE_NAME,
00445 cmds,
00446 0,
00447 params,
00448 mod_init,
00449 0,
00450 destroy_mod,
00451 0,
00452 child_init
00453 };