|
@@ -852,7 +852,6 @@ static int child_init(int rank)
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
/**************************** wrapper functions ***************************/
|
|
|
static int t_check_status(struct sip_msg* msg, char *p1, char *foo)
|
|
|
{
|
|
@@ -984,6 +983,98 @@ error:
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+static int ki_t_check_status(sip_msg_t* msg, str *sexp)
|
|
|
+{
|
|
|
+ regmatch_t pmatch;
|
|
|
+ struct cell *t;
|
|
|
+ char *status, *s = NULL;
|
|
|
+ char backup;
|
|
|
+ int lowest_status, n, ret;
|
|
|
+ regex_t re;
|
|
|
+
|
|
|
+ /* first get the transaction */
|
|
|
+ if (t_check(msg, 0 ) == -1) return -1;
|
|
|
+
|
|
|
+ if ((t = get_t()) == 0) {
|
|
|
+ LM_ERR("cannot check status for a reply"
|
|
|
+ " which has no T-state established\n");
|
|
|
+ goto error0;
|
|
|
+ }
|
|
|
+
|
|
|
+ memset(&re, 0, sizeof(regex_t));
|
|
|
+ if (regcomp(&re, sexp->s, REG_EXTENDED|REG_ICASE|REG_NEWLINE)) {
|
|
|
+ LM_ERR("Bad regular expression '%s'\n", s);
|
|
|
+ goto error0;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch(get_route_type()) {
|
|
|
+ case REQUEST_ROUTE:
|
|
|
+ /* use the status of the last sent reply */
|
|
|
+ status = int2str( t->uas.status, 0);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case TM_ONREPLY_ROUTE:
|
|
|
+ case CORE_ONREPLY_ROUTE:
|
|
|
+ /* use the status of the current reply */
|
|
|
+ status = msg->first_line.u.reply.status.s;
|
|
|
+ backup = status[msg->first_line.u.reply.status.len];
|
|
|
+ status[msg->first_line.u.reply.status.len] = 0;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case FAILURE_ROUTE:
|
|
|
+ /* use the status of the winning reply */
|
|
|
+ ret = t_pick_branch( -1, 0, t, &lowest_status);
|
|
|
+ if (ret == -1) {
|
|
|
+ /* t_pick_branch() retuns error also when there are only
|
|
|
+ * blind UACs. Let us give it another chance including the
|
|
|
+ * blind branches. */
|
|
|
+ LM_DBG("t_pick_branch returned error,"
|
|
|
+ " trying t_pick_branch_blind\n");
|
|
|
+ ret = t_pick_branch_blind(t, &lowest_status);
|
|
|
+ }
|
|
|
+ if (ret < 0) {
|
|
|
+ LM_CRIT("BUG: t_pick_branch failed to get"
|
|
|
+ " a final response in FAILURE_ROUTE\n");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+ status = int2str( lowest_status , 0);
|
|
|
+ break;
|
|
|
+ case BRANCH_FAILURE_ROUTE:
|
|
|
+ status = int2str(t->uac[get_t_branch()].last_received, 0);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ LM_ERR("unsupported route type %d\n",
|
|
|
+ get_route_type());
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
+ LM_DBG("checked status is <%s>\n",status);
|
|
|
+ /* do the checking */
|
|
|
+ n = regexec(&re, status, 1, &pmatch, 0);
|
|
|
+
|
|
|
+ regfree(&re);
|
|
|
+
|
|
|
+ if (unlikely(t && is_route_type(CORE_ONREPLY_ROUTE))){
|
|
|
+ /* t_check() above has the side effect of setting T and
|
|
|
+ * REFerencing T => we must unref and unset it. */
|
|
|
+ UNREF( t );
|
|
|
+ set_t(T_UNDEFINED, T_BR_UNDEFINED);
|
|
|
+ }
|
|
|
+ if (n!=0) return -1;
|
|
|
+ return 1;
|
|
|
+
|
|
|
+error:
|
|
|
+ regfree(&re);
|
|
|
+error0:
|
|
|
+ if (unlikely(t && is_route_type(CORE_ONREPLY_ROUTE))){
|
|
|
+ /* t_check() above has the side effect of setting T and
|
|
|
+ * REFerencing T => we must unref and unset it. */
|
|
|
+ UNREF( t );
|
|
|
+ set_t(T_UNDEFINED, T_BR_UNDEFINED);
|
|
|
+ }
|
|
|
+
|
|
|
+ return -1;
|
|
|
+}
|
|
|
|
|
|
inline static int w_t_check(struct sip_msg* msg, char* str, char* str2)
|
|
|
{
|
|
@@ -2818,6 +2909,11 @@ static sr_kemi_t tm_kemi_exports[] = {
|
|
|
{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
|
|
|
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
|
|
|
},
|
|
|
+ { str_init("tm"), str_init("t_check_status"),
|
|
|
+ SR_KEMIP_INT, ki_t_check_status,
|
|
|
+ { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
|
|
|
+ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
|
|
|
+ },
|
|
|
{ str_init("tm"), str_init("t_grep_status"),
|
|
|
SR_KEMIP_INT, t_grep_status,
|
|
|
{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
|
|
@@ -2883,4 +2979,4 @@ int mod_register(char *path, int *dlflags, void *p1, void *p2)
|
|
|
{
|
|
|
sr_kemi_modules_add(tm_kemi_exports);
|
|
|
return 0;
|
|
|
-}
|
|
|
+}
|