4 * Copyright (C) 2006 iptelorg GmbH
6 * This file is part of ser, a free SIP server.
8 * ser is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
13 * For a license to use the ser software under conditions
14 * other than those described here, or to purchase support for this
15 * software, please contact iptel.org by e-mail at the following addresses:
18 * ser is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #include "../../timer.h"
34 #include "../../timer_ticks.h"
35 #include "../../route.h"
36 #include "../../sr_module.h"
37 #include "../../mem/mem.h"
38 #include "../../mem/shm_mem.h"
39 #include "../../str.h"
40 #include "../../error.h"
41 #include "../../config.h"
42 #include "../../trim.h"
43 #include "../../select.h"
45 #include "../../select_buf.h"
47 #include "../../receive.h"
48 #include "../../ip_addr.h"
50 #include "../../receive.h"
51 #include "../../globals.h"
52 #include "../../route.h"
53 #include "../../parser/msg_parser.h"
54 #include "../../action.h"
55 #include "../../script_cb.h"
56 #include "../../dset.h"
57 #include "../../usr_avp.h"
62 #define MODULE_NAME "timer"
70 unsigned short flags; /* slow / fast */
71 struct timer_ln *link;
73 struct timer_action* next;
76 /* list of all operations */
77 static struct timer_action* timer_actions = 0;
78 static struct timer_action* pkg_timer_actions = 0;
79 static struct receive_info rcv_info;
80 static struct timer_action* timer_executed = 0;
82 #define eat_spaces(_p) \
83 while( *(_p)==' ' || *(_p)=='\t' ){\
86 #define eat_alphanum(_p) \
87 while ( (*(_p) >= 'a' && *(_p) <= 'z') || (*(_p) >= 'A' && *(_p) <= 'Z') || (*(_p) >= '0' && *(_p) <= '9') || (*(_p) == '_') ) {\
91 static struct timer_action* find_action_by_name(struct timer_action* timer_actions, char *name, int len) {
92 struct timer_action *a;
93 if (len == -1) len = strlen(name);
94 for (a=timer_actions; a; a = a->next) {
95 if (a->timer_name && strlen(a->timer_name)==len && strncmp(name, a->timer_name, len) == 0)
101 static int sel_root(str* res, select_t* s, struct sip_msg* msg) { /* dummy */
105 static int sel_timer(str* res, select_t* s, struct sip_msg* msg) {
106 struct timer_action* a;
107 if (!msg) { /* select fixup */
108 a = find_action_by_name(timer_actions /* called after mod_init */, s->params[2].v.s.s, s->params[2].v.s.len);
110 ERR(MODULE_NAME": timer_enable_fixup: timer '%.*s' not declared\n", s->params[2].v.s.len, s->params[2].v.s.s);
113 s->params[2].v.p = a;
118 static int sel_enabled(str* res, select_t* s, struct sip_msg* msg) {
119 static char buf[2] = "01";
120 if (!msg) return sel_timer(res, s, msg);
122 res->s = &buf[(((struct timer_action*) s->params[2].v.p)->link->flags & F_TIMER_ACTIVE) != 0];
126 static int sel_executed(str* res, select_t* s, struct sip_msg* msg) {
127 if (!timer_executed) return 1;
128 res->s = timer_executed->timer_name;
129 res->len = strlen(res->s);
133 select_row_t sel_declaration[] = {
134 { NULL, SEL_PARAM_STR, STR_STATIC_INIT(MODULE_NAME), sel_root, SEL_PARAM_EXPECTED},
135 { sel_root, SEL_PARAM_STR, STR_STATIC_INIT("timer"), sel_timer, SEL_PARAM_EXPECTED|CONSUME_NEXT_STR|FIXUP_CALL},
136 { sel_timer, SEL_PARAM_STR, STR_STATIC_INIT("enabled"), sel_enabled, 0},
137 { sel_root, SEL_PARAM_STR, STR_STATIC_INIT("executed"), sel_executed, 0},
139 { NULL, SEL_PARAM_STR, STR_NULL, NULL, 0}
142 static unsigned int timer_msg_no = 0;
144 static ticks_t timer_handler(ticks_t ticks, struct timer_ln* tl, void* data) {
145 /*?min length of first line of message is 16 char!?*/
146 #define MSG "GET /timer HTTP/0.9\n\n"
148 struct timer_action *a;
149 struct run_act_ctx ra_ctx;
152 if (!a->disable_itself) {
154 DEBUG(MODULE_NAME": handler: called at %d ticks, timer: '%s', pid:%d\n", ticks, a->timer_name, getpid());
156 if (a->route_no >= main_rt.idx) {
157 BUG(MODULE_NAME": invalid routing table number #%d of %d\n", a->route_no, main_rt.idx);
160 if (!main_rt.rlist[a->route_no]) {
161 WARN(MODULE_NAME": route not declared (hash:%d)\n", a->route_no);
164 msg=pkg_malloc(sizeof(struct sip_msg));
166 ERR(MODULE_NAME": handler: no mem for sip_msg\n");
170 memset(msg, 0, sizeof(struct sip_msg)); /* init everything to 0 */
173 msg->len=sizeof(MSG)-1;
176 msg->id=timer_msg_no;
177 msg->set_global_address=default_global_address;
178 msg->set_global_port=default_global_port;
180 if (parse_msg(msg->buf, msg->len, msg)!=0){
181 ERR(MODULE_NAME": handler: parse_msg failed\n");
184 /* ... clear branches from previous message */
186 reset_static_buffer();
187 if (exec_pre_script_cb(msg, REQUEST_CB_TYPE)==0 )
188 goto end; /* drop the request */
189 /* exec the routing script */
191 init_run_actions_ctx(&ra_ctx);
192 run_actions(&ra_ctx, main_rt.rlist[a->route_no], msg);
194 /* execute post request-script callbacks */
195 exec_post_script_cb(msg, REQUEST_CB_TYPE);
198 DEBUG(MODULE_NAME": handler: cleaning up\n");
204 /* begin critical section */
205 if (a->disable_itself) {
207 timer_allow_del(a->link);
209 timer_reinit(a->link);
210 a->disable_itself = 0;
211 /* end critical section */
212 return 0; /* do no call more */
215 return (ticks_t)(-1); /* periodical */
218 static int timer_enable_fixup(void** param, int param_no) {
219 struct timer_action* a;
223 a = find_action_by_name(timer_actions /* called after mod_init*/, (char*) *param, -1);
225 ERR(MODULE_NAME": timer_enable_fixup: timer '%s' not declared\n", (char*) *param);
231 /* res = fixup_int_12(param, param_no);
232 if (res < 0) return res; */
233 n=atoi((char *)*param);
234 *param = (void*)(long)(/*(int) *param*/n != 0);
241 static int timer_enable_func(struct sip_msg* m, char* timer_act, char* enable) {
242 struct timer_action* a;
244 a = (void*) timer_act;
245 en = (int)(long) enable;
246 /* timer is not deleted immediately but is removed from handler by itself because timer_del may be slow blocking procedure
247 * Disable and enable in sequence may be tricky
249 /* begin critical section */
250 if ((a->link->flags & F_TIMER_ACTIVE) == 0) {
252 timer_reinit(a->link);
253 timer_add(a->link, MS_TO_TICKS(a->interval));
254 a->disable_itself = 0;
258 if (en && a->disable_itself) {
259 a->disable_itself = 0; /* it's not 100% reliable! */
265 /* end critical section */
269 static int get_next_part(char** s, str* part, char delim) {
273 while (*c2!=delim && *c2!=0) c2++;
284 while ( c2 >= c && ((*c2 == ' ')||(*c2 == '\t')) ) c2--;
290 /* timer_id=route_no,interval_ms[,"slow"|"fast"[,"enable"]] */
291 static int declare_timer(modparam_t type, char* param) {
293 unsigned int route_no, interval, enabled, flags;
294 struct timer_action *pa;
295 char *p, *save_p, c, *timer_name;
301 if (*p != '=' || p == save_p) goto err;
305 if (find_action_by_name(pkg_timer_actions, timer_name, -1) != NULL) {
306 ERR(MODULE_NAME": declare_timer: timer '%s' already exists\n", timer_name);
311 if (!get_next_part(&p, &s, ',')) goto err;
315 n = route_get(&main_rt, s.s);
317 if (n == -1) goto err;
321 if (!get_next_part(&p, &s, ',')) goto err;
322 if (str2int(&s, &interval) < 0) goto err;
326 if (get_next_part(&p, &s, ',')) {
327 if (s.len == 4 && strncasecmp(s.s, "FAST", 4)==0)
328 flags = F_TIMER_FAST;
329 else if (s.len == 4 && strncasecmp(s.s, "SLOW", 4)==0)
336 if (get_next_part(&p, &s, ',')) {
337 if (s.len == 6 && strncasecmp(s.s, "ENABLE", 6)==0)
343 pa = pkg_malloc(sizeof(*pa)); /* cannot use shmmem here! */
345 ERR(MODULE_NAME": cannot allocate timer data\n");
348 memset(pa, 0, sizeof(*pa));
349 pa->timer_name = timer_name;
350 pa->route_no = route_no;
351 pa->interval = interval;
352 pa->enable_on_start = enabled;
354 pa->next = pkg_timer_actions;
355 pkg_timer_actions = pa;
359 ERR(MODULE_NAME": declare_timer: timer_name: '%s', error near '%s'\n", timer_name, save_p);
363 static int mod_init() {
364 struct timer_action *a, **pa;
366 DEBUG(MODULE_NAME": init: initializing, pid=%d\n", getpid());
368 /* copy from pkg to shm memory */
369 for (pa=&timer_actions; pkg_timer_actions; pa=&(*pa)->next) {
370 a = pkg_timer_actions;
371 *pa = shm_malloc(sizeof(**pa));
373 ERR(MODULE_NAME": cannot allocate timer data\n");
376 memcpy(*pa, a, sizeof(**pa));
378 pkg_timer_actions = a->next;
382 for (a=timer_actions; a; a=a->next) {
383 a->link = timer_alloc();
385 ERR(MODULE_NAME": init: cannot allocate timer\n");
388 timer_init(a->link, timer_handler, a, a->flags);
390 ERR(MODULE_NAME": init: cannot initialize timer\n");
395 memset(&rcv_info, 0, sizeof(rcv_info));
396 register_select_table(sel_declaration);
400 static int child_init(int rank) {
401 struct timer_action* a;
402 /* may I start timer in mod_init ?? */
403 if (rank!=PROC_TIMER) return 0;
404 for (a=timer_actions; a; a=a->next) {
405 if (a->enable_on_start) {
406 timer_add(a->link, MS_TO_TICKS(a->interval));
412 static void destroy_mod(void) {
413 struct timer_action* a;
414 DEBUG(MODULE_NAME": destroy: destroying, pid=%d\n", getpid());
415 while (timer_actions) {
421 timer_actions = a->next;
429 static cmd_export_t cmds[] = {
430 {MODULE_NAME"_enable", timer_enable_func, 2, timer_enable_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
435 * Exported parameters
437 static param_export_t params[] = {
438 {"declare_timer", PARAM_STRING|PARAM_USE_FUNC, (void*) declare_timer},
443 struct module_exports exports = {
445 cmds, /* Exported commands */
447 params, /* Exported parameters */
448 mod_init, /* module initialization function */
449 0, /* response function*/
450 destroy_mod, /* destroy function */
451 0, /* oncancel function */
452 child_init /* per-child init function */