diff --git a/modules/presence/doc/presence_admin.xml b/modules/presence/doc/presence_admin.xml
index f7472f9ee4d..e977699772a 100644
--- a/modules/presence/doc/presence_admin.xml
+++ b/modules/presence/doc/presence_admin.xml
@@ -322,7 +322,7 @@ modparam("presence", "expires_offset", 10)
max_expires (int)
- The the maximum admissible expires value for PUBLISH/SUBSCRIBE
+ The maximum admissible expires value for PUBLISH/SUBSCRIBE
message (in seconds).
@@ -339,6 +339,61 @@ modparam("presence", "max_expires", 3600)
+
+ min_expires (int)
+
+ The minimum admissible expires value for PUBLISH/SUBSCRIBE
+ message (in seconds).
+
+
+ If > 0 then min_expires_action parameter determines the response.
+
+
+ Default value is 0
.
+
+
+
+ Set min_expires parameter
+
+ ...
+ modparam("presence", "min_expires", 1800)
+ ...
+
+
+
+
+
+ min_expires_action (int)
+
+ The action to take when UA sends a expires value less then min_expires.
+
+
+
+ Possible Values
+
+ 1 : RFC Compliant, returns 423 Interval Too Brief
+
+
+ 2 : forces the min_expires value in the subscription
+
+
+
+
+ If > 0 then min_expires_action parameter determines the response.
+
+
+ Default value is 1
.
+
+
+ Set min_expires parameter
+
+ ...
+ modparam("presence", "min_expires", 1800)
+ ...
+
+
+
+
server_address (str)
diff --git a/modules/presence/presence.c b/modules/presence/presence.c
index 517566509b9..1a5284949d5 100644
--- a/modules/presence/presence.c
+++ b/modules/presence/presence.c
@@ -139,6 +139,8 @@ char prefix='a';
int startup_time=0;
str db_url = {0, 0};
int expires_offset = 0;
+int min_expires= 0;
+int min_expires_action= 1;
int max_expires= 3600;
int shtable_size= 9;
shtable_t subs_htable= NULL;
@@ -195,6 +197,8 @@ static param_export_t params[]={
{ "to_tag_pref", PARAM_STRING, &to_tag_pref },
{ "expires_offset", INT_PARAM, &expires_offset },
{ "max_expires", INT_PARAM, &max_expires },
+ { "min_expires", INT_PARAM, &min_expires },
+ { "min_expires_action", INT_PARAM, &min_expires_action },
{ "server_address", PARAM_STR, &server_address},
{ "subs_htable_size", INT_PARAM, &shtable_size},
{ "pres_htable_size", INT_PARAM, &phtable_size},
@@ -274,6 +278,17 @@ static int mod_init(void)
if(max_expires<= 0)
max_expires = 3600;
+ if(min_expires < 0)
+ min_expires = 0;
+
+ if(min_expires > max_expires)
+ min_expires = max_expires;
+
+ if(min_expires_action < 1 || min_expires_action > 2) {
+ LM_ERR("min_expires_action must be 1 = RFC 6665/3261 Reply 423, 2 = force min_expires value\n");
+ return -1;
+ }
+
if(server_address.s== NULL)
LM_DBG("server_address parameter not set in configuration file\n");
diff --git a/modules/presence/presence.h b/modules/presence/presence.h
index c1bd288a79d..b725bad5779 100644
--- a/modules/presence/presence.h
+++ b/modules/presence/presence.h
@@ -76,6 +76,8 @@ extern int startup_time;
extern char *to_tag_pref;
extern int expires_offset;
extern str server_address;
+extern int min_expires;
+extern int min_expires_action;
extern int max_expires;
extern int subs_dbmode;
extern int publ_cache_enabled;
diff --git a/modules/presence/subscribe.c b/modules/presence/subscribe.c
index 334dc323d87..48938fce725 100644
--- a/modules/presence/subscribe.c
+++ b/modules/presence/subscribe.c
@@ -58,6 +58,7 @@ static str pu_481_rpl = str_init("Subscription does not exist");
static str pu_400_rpl = str_init("Bad request");
static str pu_500_rpl = str_init("Server Internal Error");
static str pu_489_rpl = str_init("Bad Event");
+static str pu_423_rpl = str_init("Interval Too Brief");
int send_2XX_reply(struct sip_msg * msg, int reply_code, int lexpire,
str* local_contact)
@@ -863,11 +864,10 @@ int handle_subscribe(struct sip_msg* msg, str watcher_user, str watcher_domain)
ev_param= ev_param->next;
}
- if(extract_sdialog_info(&subs, msg, max_expires, &to_tag_gen,
- server_address, watcher_user, watcher_domain)< 0)
+ if(extract_sdialog_info_ex(&subs, msg, min_expires, max_expires, &to_tag_gen,
+ server_address, watcher_user, watcher_domain, &reply_code, &reply_str)< 0)
{
- LM_ERR("failed to extract dialog information\n");
- goto error;
+ goto error;
}
if (pres_notifier_processes > 0 && pa_dbf.start_transaction)
@@ -1088,9 +1088,10 @@ int handle_subscribe(struct sip_msg* msg, str watcher_user, str watcher_domain)
}
-int extract_sdialog_info(subs_t* subs,struct sip_msg* msg, int mexp,
- int* to_tag_gen, str scontact, str watcher_user,
- str watcher_domain)
+int extract_sdialog_info_ex(subs_t* subs,struct sip_msg* msg, int miexp,
+ int mexp, int* to_tag_gen, str scontact,
+ str watcher_user, str watcher_domain,
+ int* reply_code, str* reply_str)
{
str rec_route= {0, 0};
int rt = 0;
@@ -1120,6 +1121,18 @@ int extract_sdialog_info(subs_t* subs,struct sip_msg* msg, int mexp,
if(lexpire > mexp)
lexpire = mexp;
+ if (lexpire && miexp && lexpire < miexp) {
+ if(min_expires_action == 1) {
+ LM_DBG("subscription expiration invalid , requested=%d, minimum=%d, returning error \"423 Interval Too brief\"\n", lexpire, miexp);
+ *reply_code = INTERVAL_TOO_BRIEF;
+ *reply_str = pu_423_rpl;
+ goto error;
+ } else {
+ LM_DBG("subscription expiration set to minimum (%d) for requested (%d)\n", lexpire, miexp);
+ lexpire = miexp;
+ }
+ }
+
subs->expires = lexpire;
if( msg->to==NULL || msg->to->body.s==NULL)
@@ -1325,6 +1338,15 @@ int extract_sdialog_info(subs_t* subs,struct sip_msg* msg, int mexp,
return -1;
}
+int extract_sdialog_info(subs_t* subs,struct sip_msg* msg, int mexp,
+ int* to_tag_gen, str scontact,
+ str watcher_user, str watcher_domain)
+{
+ int reply_code = 500;
+ str reply_str = pu_500_rpl;
+ return extract_sdialog_info_ex(subs, msg, min_expires, mexp, to_tag_gen,
+ scontact, watcher_user, watcher_domain, &reply_code, &reply_str);
+}
int get_stored_info(struct sip_msg* msg, subs_t* subs, int* reply_code,
str* reply_str)
diff --git a/modules/presence/subscribe.h b/modules/presence/subscribe.h
index 00c02a3a0cd..776d8dadd89 100644
--- a/modules/presence/subscribe.h
+++ b/modules/presence/subscribe.h
@@ -113,11 +113,14 @@ void update_db_subs_timer(db1_con_t *db,db_func_t dbf, shtable_t hash_table,
typedef void (*update_db_subs_t)(db1_con_t * ,db_func_t ,shtable_t ,int ,int ,
handle_expired_func_t);
+int extract_sdialog_info_ex(subs_t* subs,struct sip_msg* msg, int min_expire,
+ int max_expire, int* to_tag_gen, str scontact, str watcher_user,
+ str watcher_domain, int* reply_code,str* reply_txt);
int extract_sdialog_info(subs_t* subs,struct sip_msg* msg, int max_expire,
int* to_tag_gen, str scontact, str watcher_user, str watcher_domain);
typedef int (*extract_sdialog_info_t)(subs_t* subs, struct sip_msg* msg,
- int max_expire, int* to_tag_gen, str scontact, str watcher_user,
- str watcher_domain);
+ int max_expire, int* to_tag_gen, str scontact, str watcher_user,
+ str watcher_domain);
void delete_subs(str* pres_uri, str* ev_name, str* to_tag, str* from_tag, str* callid);
#endif
diff --git a/modules/presence/utils_func.c b/modules/presence/utils_func.c
index e7dbd06be20..64d0527ccb2 100644
--- a/modules/presence/utils_func.c
+++ b/modules/presence/utils_func.c
@@ -102,13 +102,13 @@ int a_to_i (char *s,int len)
int send_error_reply(struct sip_msg* msg, int reply_code, str reply_str)
{
- if(reply_code== BAD_EVENT_CODE)
- {
- str hdr_append;
- char buffer[256];
- int i;
- pres_ev_t* ev= EvList->events;
+ str hdr_append;
+ char buffer[256];
+ int i;
+ pres_ev_t* ev= EvList->events;
+ if(reply_code== BAD_EVENT_CODE)
+ {
hdr_append.s = buffer;
hdr_append.s[0]='\0';
hdr_append.len = sprintf(hdr_append.s, "Allow-Events: ");
@@ -138,7 +138,26 @@ int send_error_reply(struct sip_msg* msg, int reply_code, str reply_str)
LM_ERR("unable to add lump_rl\n");
return -1;
}
- }
+ } else if(reply_code== INTERVAL_TOO_BRIEF) {
+
+ hdr_append.s = buffer;
+ hdr_append.s[0]='\0';
+ hdr_append.len = sprintf(hdr_append.s, "Min-Expires: %d", min_expires);
+ if(hdr_append.len < 0)
+ {
+ LM_ERR("unsuccessful sprintf\n");
+ return -1;
+ }
+ memcpy(hdr_append.s+ hdr_append.len, CRLF, CRLF_LEN);
+ hdr_append.len+= CRLF_LEN;
+ hdr_append.s[hdr_append.len]= '\0';
+
+ if (add_lump_rpl( msg, hdr_append.s, hdr_append.len, LUMP_RPL_HDR)==0 )
+ {
+ LM_ERR("unable to add lump_rl\n");
+ return -1;
+ }
+ }
if (slb.freply(msg, reply_code, &reply_str) < 0)
{
diff --git a/modules/presence/utils_func.h b/modules/presence/utils_func.h
index bb3a1810ebc..cf7c030b7b6 100644
--- a/modules/presence/utils_func.h
+++ b/modules/presence/utils_func.h
@@ -47,6 +47,7 @@
#define LCONTACT_BUF_SIZE 1024
#define BAD_EVENT_CODE 489
+#define INTERVAL_TOO_BRIEF 423
#define EVENT_DIALOG_SLA(ev) \