Browse Source

dialog: refresh cseq update if it was incremented in the past

- reported by GH #752
Daniel-Constantin Mierla 9 years ago
parent
commit
e349af5516
3 changed files with 77 additions and 5 deletions
  1. 65 3
      modules/dialog/dlg_cseq.c
  2. 3 0
      modules/dialog/dlg_cseq.h
  3. 9 2
      modules/dialog/dlg_handlers.c

+ 65 - 3
modules/dialog/dlg_cseq.c

@@ -186,6 +186,61 @@ error:
 	return -1;
 }
 
+
+/**
+ *
+ */
+int dlg_cseq_refresh(sip_msg_t *msg, dlg_cell_t *dlg,
+		unsigned int direction)
+{
+	str nval;
+	str *pval;
+
+	if(dlg_cseq_prepare_msg(msg)!=0) {
+		goto error;
+	}
+	if(msg->first_line.type==SIP_REPLY) {
+		/* nothing to do for outgoing replies */
+		goto done;
+	}
+
+	LM_DBG("initiating cseq refresh\n");
+
+	/* supported only for downstrem direction */
+	if(direction != DLG_DIR_DOWNSTREAM) {
+		LM_DBG("request not going downstream (%u)\n", direction);
+		goto done;
+	}
+
+	/* take the increment value from dialog */
+	if(!((dlg->iflags&DLG_IFLAG_CSEQ_DIFF)==DLG_IFLAG_CSEQ_DIFF)) {
+		LM_DBG("no cseq refresh required\n");
+		goto done;
+	}
+
+	/* get dialog variable holding cseq diff */
+	pval = get_dlg_variable(dlg, &_dlg_cseq_diff_var_name);
+	if(pval==NULL || pval->s==NULL || pval->len<=0) {
+		LM_DBG("dialog marked with cseq diff but no variable set yet\n");
+		goto done;
+	}
+
+	nval = *pval;
+	trim(&nval);
+
+	LM_DBG("adding cseq refresh header value: %.*s\n", nval.len, nval.s);
+	parse_headers(msg, HDR_EOH_F, 0);
+	sr_hdr_add_zs(msg, "P-K-CSeq-Refresh", &nval);
+
+done:
+	if(dlg!=NULL) dlg_release(dlg);
+	return 0;
+
+error:
+	if(dlg!=NULL) dlg_release(dlg);
+	return -1;
+}
+
 /**
  *
  */
@@ -319,15 +374,22 @@ int dlg_cseq_msg_sent(void *data)
 		parse_headers(&msg, HDR_EOH_F, 0);
 		hfk = sr_hdr_get_z(&msg, "P-K-Auth-CSeq");
 		if(hfk!=NULL) {
-			LM_DBG("uac auth request - cseq inc needed\n");
+			LM_DBG("new cseq inc requested\n");
 			nval = hfk->body;
 			trim(&nval);
 		} else {
-			LM_DBG("uac auth request - cseq inc not needed\n");
-			goto done;
+			LM_DBG("new cseq inc not requested\n");
 		}
 	}
 
+	if(nval.len<=0) {
+		hfk = sr_hdr_get_z(&msg, "P-K-CSeq-Refresh");
+		if(hfk!=NULL) {
+			LM_DBG("cseq refresh requested\n");
+			nval = hfk->body;
+			trim(&nval);
+		}
+	}
 	if(nval.len<=0) {
 		goto done;
 	}

+ 3 - 0
modules/dialog/dlg_cseq.h

@@ -32,9 +32,12 @@
 #define _DLG_CSEQ_H_
 
 #include "../../parser/msg_parser.h"
+#include "dlg_hash.h"
 
 int dlg_register_cseq_callbacks(void);
 
 int dlg_cseq_update(sip_msg_t *msg);
+int dlg_cseq_refresh(sip_msg_t *msg, dlg_cell_t *dlg,
+		unsigned int direction);
 
 #endif

+ 9 - 2
modules/dialog/dlg_handlers.c

@@ -48,6 +48,7 @@
 #include "dlg_hash.h"
 #include "dlg_timer.h"
 #include "dlg_cb.h"
+#include "dlg_cseq.h"
 #include "dlg_handlers.h"
 #include "dlg_req_within.h"
 #include "dlg_db_handler.h"
@@ -1158,7 +1159,7 @@ dlg_cell_t *dlg_get_msg_dialog(sip_msg_t *msg)
 
 /*!
  * \brief Function that is registered as RR callback for dialog tracking
- * 
+ *
  * Function that is registered as RR callback for dialog tracking. It
  * sets the appropriate events after the SIP method and run the state
  * machine to update the dialog state. It updates then the saved
@@ -1250,7 +1251,7 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
 	}
 
 	if (dlg==0) {
-		if (pre_match_parse( req, &callid, &ftag, &ttag, 1)<0)
+		if (pre_match_parse(req, &callid, &ftag, &ttag, 1)<0)
 			return;
 		/* TODO - try to use the RR dir detection to speed up here the
 		 * search -bogdan */
@@ -1267,6 +1268,12 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
     _dlg_ctx.iuid.h_entry = dlg->h_entry;
     _dlg_ctx.iuid.h_id = dlg->h_id;
 
+	if(dlg->iflags & DLG_IFLAG_CSEQ_DIFF) {
+		if(dlg_cseq_refresh(req, dlg, dir)<0) {
+			LM_ERR("failed to refresh cseq update\n");
+		}
+	}
+
 	if (req->first_line.u.request.method_value != METHOD_ACK) {
 		iuid = dlg_get_iuid_shm_clone(dlg);
 		if(iuid!=NULL)