Beispiel #1
0
static ticks_t timer_handler(ticks_t ticks, struct timer_ln* tl, void* data) {
	/*?min length of first line of message is 16 char!?*/
	#define MSG "GET /timer HTTP/0.9\n\n"
	struct sip_msg* msg;
	struct timer_action *a;
	struct run_act_ctx ra_ctx;

	a = data;
	if (!a->disable_itself) {

		DEBUG(MODULE_NAME": handler: called at %d ticks, timer: '%s', pid:%d\n", ticks, a->timer_name, getpid());

		if (a->route_no >= main_rt.idx) {
			BUG(MODULE_NAME": invalid routing table number #%d of %d\n", a->route_no, main_rt.idx);
			goto err2;
		}
		if (!main_rt.rlist[a->route_no]) {
			WARN(MODULE_NAME": route not declared (hash:%d)\n", a->route_no);
			goto err2;
		}
		msg=pkg_malloc(sizeof(struct sip_msg));
		if (msg==0) {
			ERR(MODULE_NAME": handler: no mem for sip_msg\n");
			goto err2;
		}
		timer_msg_no++;
		memset(msg, 0, sizeof(struct sip_msg)); /* init everything to 0 */

		msg->buf=MSG;
		msg->len=sizeof(MSG)-1;

		msg->rcv= rcv_info;
		msg->id=timer_msg_no;
		msg->set_global_address=default_global_address;
		msg->set_global_port=default_global_port;

		if (parse_msg(msg->buf, msg->len, msg)!=0){
			ERR(MODULE_NAME": handler: parse_msg failed\n");
			goto err;
		}
		/* ... clear branches from previous message */
		clear_branches();
		reset_static_buffer();
		if (exec_pre_req_cb(msg)==0 )
			goto end; /* drop the request */
		/* exec the routing script */
		timer_executed = a;
		init_run_actions_ctx(&ra_ctx);
		run_actions(&ra_ctx, main_rt.rlist[a->route_no], msg);
		timer_executed = 0;
		/* execute post request-script callbacks */
		exec_post_req_cb(msg);
	end:
		reset_avps();
		DEBUG(MODULE_NAME": handler: cleaning up\n");
	err:
		free_sip_msg(msg);
		pkg_free(msg);
	err2:	;
	}
        /* begin critical section */
	if (a->disable_itself) {

		timer_allow_del(a->link);
		timer_del(a->link);
		timer_reinit(a->link);
		a->disable_itself = 0;
	        /* end critical section */
		return 0;   /* do no call more */
	}
	else
        	return (ticks_t)(-1); /* periodical */
}
Beispiel #2
0
/* the following assumption are made (to avoid deleting/re-adding the timer):
 *  retr_buf->retr_interval < ( 1<<((sizeof(ticks_t)*8-1) )
 *  if retr_buf->retr_interval==0 => timer disabled
 *                            ==(ticks_t) -1 => retr. disabled (fr working)
 *     retr_buf->retr_interval & (1 <<(sizeof(ticks_t)*8-1) => retr. & fr reset
 *     (we never reset only retr, it's either reset both of them or retr
 *      disabled & reset fr). In this case the fr_origin will contain the
 *      "time" of the reset and next retr should occur at
 *      fr->origin+retr_interval (we also assume that we'll never reset retr
 *      to a lower value then the current one)
 */
ticks_t retr_buf_handler(ticks_t ticks, struct timer_ln *tl, void *p)
{
	struct retr_buf *rbuf;
	ticks_t fr_remainder;
	ticks_t retr_remainder;
	ticks_t retr_interval;
	unsigned long new_retr_interval_ms;
	unsigned long crt_retr_interval_ms;
	struct cell *t;

	rbuf = (struct retr_buf *)((void *)tl
							   - (void *)(&((struct retr_buf *)0)->timer));
	membar_depends(); /* to be on the safe side */
	t = rbuf->my_T;

#ifdef TIMER_DEBUG
	LM_DBG("timer retr_buf_handler @%d (%p -> %p -> %p)\n", ticks, tl, rbuf, t);
#endif
	if(unlikely(rbuf->flags & F_RB_DEL_TIMER)) {
		/* timer marked for deletion */
		rbuf->t_active = 0; /* mark it as removed */
		/* a membar is not really needed, in the very unlikely case that
		 * another process will see old t_active's value and will try to
		 * delete the timer again, but since timer_del it's safe in this cases
		 * it will be a no-op */
		return 0;
	}
	/* overflow safe check (should work ok for fr_intervals < max ticks_t/2) */
	if((s_ticks_t)(rbuf->fr_expire - ticks) <= 0) {
		/* final response */
		rbuf->t_active = 0; /* mark the timer as removed
							 (both timers disabled)
							  a little race risk, but
							  nothing bad would happen */
		rbuf->flags |= F_RB_TIMEOUT;
		/* WARNING:  the next line depends on taking care not to start the
		 *           wait timer before finishing with t (if this is not
		 *           guaranteed then comment the timer_allow_del() line) */
		timer_allow_del(); /* [optional] allow timer_dels, since we're done
							  and there is no race risk */
		final_response_handler(rbuf, t);
		return 0;
	} else {
		/*  4 possible states running (t1), t2, paused, disabled */
		if((s_ticks_t)(rbuf->retr_expire - ticks) <= 0) {
			if(rbuf->flags & F_RB_RETR_DISABLED)
				goto disabled;
			crt_retr_interval_ms = (unsigned long)p;
			/* get the  current interval from timer param. */
			if(unlikely((rbuf->flags & F_RB_T2)
						|| (crt_retr_interval_ms > RT_T2_TIMEOUT_MS(rbuf)))) {
				retr_interval = MS_TO_TICKS(RT_T2_TIMEOUT_MS(rbuf));
				new_retr_interval_ms = RT_T2_TIMEOUT_MS(rbuf);
			} else {
				retr_interval = MS_TO_TICKS(crt_retr_interval_ms);
				new_retr_interval_ms = crt_retr_interval_ms << 1;
			}
#ifdef TIMER_DEBUG
			LM_DBG("new interval %ld ms / %d ticks"
				   " (max %d ms)\n",
					new_retr_interval_ms, retr_interval,
					RT_T2_TIMEOUT_MS(rbuf));
#endif
			/* we could race with the reply_received code, but the
				 * worst thing that can happen is to delay a reset_to_t2
				 * for crt_interval and send an extra retr.*/
			rbuf->retr_expire = ticks + retr_interval;
			/* set new interval to -1 on error, or retr_int. on success */
			retr_remainder = retransmission_handler(rbuf) | retr_interval;
			/* store the next retr. interval in ms inside the timer struct,
				 * in the data member */
			tl->data = (void *)(new_retr_interval_ms);
		} else {
			retr_remainder = rbuf->retr_expire - ticks;
			LM_DBG("retr - nothing to do, expire in %d\n", retr_remainder);
		}
	}
	/* skip: */
	/* return minimum of the next retransmission handler and the
	 * final response (side benefit: it properly cancels timer if ret==0 and
	 *  sleeps for fr_remainder if retr. is canceled [==(ticks_t)-1]) */
	fr_remainder = rbuf->fr_expire - ticks; /* to be more precise use
											get_ticks_raw() instead of ticks
											(but make sure that
											crt. ticks < fr_expire */
#ifdef TIMER_DEBUG
	LM_DBG("timer retr_buf_handler @%d (%p ->%p->%p) exiting min (%d, %d)\n",
			ticks, tl, rbuf, t, retr_remainder, fr_remainder);
#endif
#ifdef EXTRA_DEBUG
	if(retr_remainder == 0 || fr_remainder == 0) {
		LM_BUG("0 remainder => disabling timer!: "
			   "retr_remainder=%d, fr_remainder=%d\n",
				retr_remainder, fr_remainder);
	}
#endif
	if(retr_remainder < fr_remainder)
		return retr_remainder;
	else {
/* hack to switch to the slow timer */
#ifdef TM_FAST_RETR_TIMER
		tl->flags &= ~F_TIMER_FAST;
#endif
		return fr_remainder;
	}
disabled:
	return rbuf->fr_expire - ticks;
}