Browse Source

added module presence_conference to master branch

mariusbucur 15 years ago
parent
commit
70b39e55c2
24 changed files with 1308 additions and 0 deletions
  1. 33 0
      modules_k/presence_conference/Makefile
  2. 3 0
      modules_k/presence_conference/README
  3. 69 0
      modules_k/presence_conference/add_events.c
  4. 33 0
      modules_k/presence_conference/add_events.h
  5. 4 0
      modules_k/presence_conference/doc/Makefile
  6. 266 0
      modules_k/presence_conference/notify_body.c
  7. 41 0
      modules_k/presence_conference/notify_body.h
  8. 201 0
      modules_k/presence_conference/pidf.c
  9. 53 0
      modules_k/presence_conference/pidf.h
  10. 133 0
      modules_k/presence_conference/presence_conference.c
  11. 33 0
      modules_k/presence_conference/presence_conference.h
  12. 0 0
      modules_k/presence_conference/publish.xml
  13. 72 0
      modules_k/presence_conference/test_framework/client.sh
  14. 53 0
      modules_k/presence_conference/test_framework/dereg.sh
  15. 8 0
      modules_k/presence_conference/test_framework/functions/notify.sh
  16. 23 0
      modules_k/presence_conference/test_framework/functions/publish.sh
  17. 22 0
      modules_k/presence_conference/test_framework/functions/register.sh
  18. 25 0
      modules_k/presence_conference/test_framework/functions/subscribe.sh
  19. 0 0
      modules_k/presence_conference/test_framework/publish.xml
  20. 63 0
      modules_k/presence_conference/test_framework/scen.sh
  21. 17 0
      modules_k/presence_conference/test_framework/xml/notify.xml
  22. 103 0
      modules_k/presence_conference/test_framework/xml/publish.xml
  23. 18 0
      modules_k/presence_conference/test_framework/xml/register.xml
  24. 35 0
      modules_k/presence_conference/test_framework/xml/subscribe.xml

+ 33 - 0
modules_k/presence_conference/Makefile

@@ -0,0 +1,33 @@
+#
+# Presence_Conference Makefile
+# 
+# 
+# WARNING: do not run this directly, it should be run by the master Makefile
+
+include ../../Makefile.defs
+auto_gen=
+NAME=presence_conference.so
+DEFS+=-I/usr/include/libxml2 -I$(LOCALBASE)/include/libxml2 \
+      -I$(LOCALBASE)/include
+LIBS+=-L$(SYSBASE)/include/lib  -L$(LOCALBASE)/lib -lxml2
+
+DEFS+=-DOPENSER_MOD_INTERFACE
+
+include ../../Makefile.modules
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 3 - 0
modules_k/presence_conference/README

@@ -0,0 +1,3 @@
+presence_conference Module
+
+Bucur Marius

+ 69 - 0
modules_k/presence_conference/add_events.c

@@ -0,0 +1,69 @@
+/*
+ * add "conference" event to presence module - mariusbucur
+ * 
+ * Copyright (C) 2010 Marius Bucur
+ * Copyright (C) 2007 Juha Heinanen
+ * Copyright (C) 2008 Klaus Darilion, IPCom
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * History:
+ * --------
+ * 2010-07-12  initial version (mariusbucur)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "../../parser/parse_content.h"
+#include "../presence/event_list.h"
+#include "presence_conference.h"
+#include "notify_body.h"
+
+int conference_add_events(void)
+{
+    pres_ev_t event;
+	
+    /* constructing "conference" event and add it to the list of events packages supported */
+    memset(&event, 0, sizeof(pres_ev_t));
+    event.name.s = "conference";
+    event.name.len = 10;
+
+    event.content_type.s = "application/conference-info+xml";
+    event.content_type.len = 31;
+
+    event.default_expires= 3600;
+    event.type = PUBL_TYPE;
+    event.req_auth = 0;
+    event.evs_publ_handl = 0;
+
+    /* aggregate XML body and free() fuction */
+    event.agg_nbody = conf_agg_nbody;
+    event.free_body = free_xml_body;
+
+    /* modify XML body for each watcher to set the correct "version" */
+    event.aux_body_processing = conf_body_setversion;
+
+	
+    if (pres_add_event(&event) < 0) {
+		LM_ERR("failed to add event \"conference\"\n");
+		return -1;
+    }
+	
+    return 0;
+}
+ 

+ 33 - 0
modules_k/presence_conference/add_events.h

@@ -0,0 +1,33 @@
+/*
+ * presence_conference module - add_event header file mariusbucur
+ *
+ * Copyright (C) 2007 Juha Heinanen
+ * Copyright (C) 2008 Klaus Darilion, IPCom
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * History:
+ * --------
+ * 2010-07-12  initial version (mariusbucur)
+ */
+
+#ifndef _CONF_ADD_EV_H_
+#define _CONF_ADD_EV_H_
+
+int conference_add_events(void);
+
+#endif

+ 4 - 0
modules_k/presence_conference/doc/Makefile

@@ -0,0 +1,4 @@
+docs = presence_xml.xml
+
+docbook_dir = ../../../docbook
+include $(docbook_dir)/Makefile.module

+ 266 - 0
modules_k/presence_conference/notify_body.c

@@ -0,0 +1,266 @@
+/*
+ * presence_conference module - mariusbucur
+ *
+ * Copyright (C) 2010 Marius Bucur
+ * Copyright (C) 2006 Voice Sistem S.R.L.
+ * Copyright (C) 2008 Klaus Darilion, IPCom
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * History:
+ * --------
+ * 2010-07-12  initial version (mariusbucur)
+ */
+/*! \file
+ * \brief Kamailio Presence_Conference :: Notify body handling
+ * \ingroup presence_conference
+ */
+
+#define MAX_INT_LEN 11 /* 2^32: 10 chars + 1 char sign */
+
+#include <string.h>
+#include <stdlib.h>
+#include <libxml/parser.h>
+
+#include "../../mem/mem.h"
+#include "../presence/utils_func.h"
+#include "../presence/hash.h"
+#include "../presence/event_list.h"
+#include "../presence/presence.h"
+#include "../presence/presentity.h"
+#include "notify_body.h"
+#include "pidf.h"
+
+str* agregate_xmls(str* pres_user, str* pres_domain, str** body_array, int n, int off_index);
+
+void free_xml_body(char* body)
+{
+	if(body== NULL)
+		return;
+
+	xmlFree(body);
+}
+
+
+str* conf_agg_nbody(str* pres_user, str* pres_domain, str** body_array, int n, int off_index)
+{
+	str* n_body= NULL;
+
+	LM_DBG("[pres_user]=%.*s [pres_domain]= %.*s, [n]=%d\n",
+			pres_user->len, pres_user->s, pres_domain->len, pres_domain->s, n);
+
+	if(body_array== NULL)
+		return NULL;
+
+	n_body = agregate_xmls(pres_user, pres_domain, body_array, n, off_index);
+	LM_DBG("[n_body]=%p\n", n_body);
+	if(n_body) {
+		LM_DBG("[*n_body]=%.*s\n",
+			n_body->len, n_body->s);
+	}
+	if(n_body== NULL && n!= 0)
+	{
+		LM_ERR("while aggregating body\n");
+	}
+
+	return n_body;
+}	
+
+str* agregate_xmls(str* pres_user, str* pres_domain, str** body_array, int n, int off_index)
+{
+	int i, j = 0;
+	
+	if(body_array == NULL || n == 0)
+		return 0;
+
+	xmlDocPtr  doc = NULL;
+	xmlNodePtr root_node = NULL;
+	xmlNsPtr   namespace = NULL;
+
+	xmlNodePtr p_root= NULL;
+	xmlDocPtr* xml_array ;
+	xmlNodePtr node = NULL;
+	str *body= NULL;
+	char buf[MAX_URI_SIZE+1];
+
+	LM_DBG("[pres_user]=%.*s [pres_domain]= %.*s, [n]=%d\n",
+			pres_user->len, pres_user->s, pres_domain->len, pres_domain->s, n);
+
+	xml_array = (xmlDocPtr*)pkg_malloc( n*sizeof(xmlDocPtr) );
+	if(unlikely(xml_array == NULL))
+	{
+		LM_ERR("while allocating memory");
+		return NULL;
+	}
+	memset(xml_array, 0, n*sizeof(xmlDocPtr)) ;
+
+	/* parse all the XML documents */
+	for(i=0; i<n; i++)
+	{
+		if(body_array[i] == NULL )
+			continue;
+
+		xml_array[j] = xmlParseMemory( body_array[i]->s, body_array[i]->len );
+		
+		/* LM_DBG("parsing XML body: [n]=%d, [i]=%d, [j]=%d xml_array[j]=%p\n", n, i, j, xml_array[j] ); */
+
+		if(unlikely(xml_array[j] == NULL))
+		{
+			LM_ERR("while parsing xml body message\n");
+			goto error;
+		}
+		j++;
+		
+	}
+
+	if(j == 0)  /* no body */
+	{
+		if(xml_array)
+			pkg_free(xml_array);
+		return NULL;
+	}
+
+	/* n: number of bodies in total */
+	/* j: number of useful bodies; created XML structures */
+	/* i: loop counter */
+	/* LM_DBG("number of bodies in total [n]=%d, number of useful bodies [j]=%d\n", n, j ); */
+
+	/* create the new NOTIFY body  */
+	if ( (pres_user->len + pres_domain->len + 1) > MAX_URI_SIZE ) {
+		LM_ERR("entity URI too long, maximum=%d\n", MAX_URI_SIZE);
+		return NULL;
+	}
+	memcpy(buf, pres_user->s, pres_user->len);
+	buf[pres_user->len] = '@';
+	memcpy(buf + pres_user->len + 1, pres_domain->s, pres_domain->len);
+	buf[pres_user->len + 1 + pres_domain->len]= '\0';
+
+	doc = xmlNewDoc(BAD_CAST "1.0");
+	if(unlikely(doc == NULL))
+		goto error;
+
+	root_node = xmlNewNode(NULL, BAD_CAST "conference-info");
+	if(unlikely(root_node == NULL))
+		goto error;
+
+	xmlDocSetRootElement(doc, root_node);
+	namespace = xmlNewNs(root_node, BAD_CAST "urn:ietf:params:xml:ns:conference-info", NULL);
+	if (unlikely(namespace == NULL)) {
+		LM_ERR("creating namespace failed\n");
+		goto error;
+	}
+	xmlSetNs(root_node, namespace);
+	/* The version must be increased for each new document and is a 32bit int.
+	   The aux_body_processing function will take care of setting the right attribute
+	   depending on the subscription for which the notify is being sent.
+	*/
+	xmlNewProp(root_node, BAD_CAST "version", BAD_CAST "0");
+	xmlNewProp(root_node, BAD_CAST "state", BAD_CAST "full" );
+	xmlNewProp(root_node, BAD_CAST "entity", BAD_CAST buf);
+
+	/* loop over all bodies and create the aggregated body */
+	for(i=0; i<j; i++)
+	{
+		p_root= xmlDocGetRootElement(xml_array[i]);
+		if(unlikely(p_root == NULL)) {
+			LM_ERR("while geting the xml_tree root element\n");
+			goto error;
+		}
+		/* just checking that the root element is "conference-info" as it should RFC4575 */
+		if(unlikely(xmlStrcasecmp(p_root->name, BAD_CAST "conference-info") != 0))
+		{
+			LM_ERR("root element is not \"conference-info\"\n");
+			goto error;
+		}
+		/* the root "conference-info" element should always have children */
+		if (p_root->children) {
+			for (node = p_root->children; node != NULL; node = node->next) {
+					if(xmlAddChild(root_node, xmlCopyNode(node, 1)) == NULL) {
+						LM_ERR("while adding child\n");
+						goto error;
+					}
+			}
+		}
+		/* we only take the most recent subscription as
+		   in this phase non partial states will be sent
+		*/
+		if(i != off_index)
+			break;
+	}
+
+	body = (str*)pkg_malloc(sizeof(str));
+	if(body == NULL) {
+		ERR_MEM(PKG_MEM_STR);
+	}
+
+	xmlDocDumpFormatMemory(doc,(xmlChar**)(void*)&body->s, 
+			&body->len, 1);	
+
+	for(i=0; i<j; i++)
+	{
+		if(xml_array[i]!=NULL)
+			xmlFreeDoc(xml_array[i]);
+	}
+	if (doc)
+		xmlFreeDoc(doc);
+	if(xml_array!=NULL)
+		pkg_free(xml_array);
+    
+	return body;
+
+error:
+	LM_ERR("error in presence_conference agg_nbody\n");
+	if(xml_array!=NULL)
+	{
+		for(i=0; i<j; i++)
+		{
+			if(xml_array[i]!=NULL)
+				xmlFreeDoc(xml_array[i]);
+		}
+		pkg_free(xml_array);
+	}
+	if(body)
+		pkg_free(body);
+
+	return NULL;
+}
+
+str *conf_body_setversion(subs_t *subs, str *body) {
+	char version_str[MAX_INT_LEN + 2];//for the null terminating character \0
+	snprintf(version_str, MAX_INT_LEN, "%d", subs->version);
+	if (!body) {
+		return NULL;
+	}
+	
+	xmlDocPtr doc = xmlParseMemory(body->s, body->len);
+	if(!doc) {
+		goto error;
+	}
+	xmlNodePtr conf_info = xmlDocGetRootElement(doc);
+	if(!conf_info) {
+		goto error;
+	}
+	if(!xmlSetProp(conf_info, BAD_CAST "version", BAD_CAST version_str)) {
+		goto error;
+	}
+	xmlDocDumpFormatMemory(doc,(xmlChar**)(void*)&body->s, 
+			&body->len, 1);
+	return NULL;
+error:
+	LM_ERR("error in presence_conference conf_body_setversion\n");
+	return NULL;
+}

+ 41 - 0
modules_k/presence_conference/notify_body.h

@@ -0,0 +1,41 @@
+/*
+ *
+ * presence_conference module - notify_body header file mariusbucur
+ *
+ * Copyright (C) 2006 Voice Sistem S.R.L.
+ * Copyright (C) 2008 Klaus Darilion, IPCom
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * History:
+ * --------
+ * 2010-07-12  initial version (mariusbucur)
+ */
+/*! \file
+ * \brief Kamailio Presence_Conference :: Notify body handling
+ * \ingroup presence_conference
+ */
+
+#ifndef _CONF_NBODY_H_
+#define _CONF_NBODY_H_
+
+str* conf_agg_nbody(str* pres_user, str* pres_domain, str** body_array,
+		int n, int off_index);
+str* conf_body_setversion(subs_t *subs, str* body);
+void free_xml_body(char* body);
+
+#endif

+ 201 - 0
modules_k/presence_conference/pidf.c

@@ -0,0 +1,201 @@
+/*
+ * $Id: pidf.c 1953 2007-04-04 08:50:33Z anca_vamanu $
+ *
+ * presence module - presence server implementation
+ *
+ * Copyright (C) 2006 Voice Sistem S.R.L.
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * History:
+ * --------
+ *  2007-04-14  initial version (anca)
+ */
+
+/*! \file
+ * \brief Kamailio Presence_XML ::  PIDF handling
+ * \ingroup presence_xml
+ */
+
+/**
+ * make strptime available
+ * use 600 for 'Single UNIX Specification, Version 3'
+ * _XOPEN_SOURCE creates conflict in header definitions in Solaris
+ */
+#ifndef __OS_solaris
+	#define _XOPEN_SOURCE 600          /* glibc2 on linux, bsd */
+	#define _BSD_SOURCE 1				/* needed on linux to "fix" the effect
+										  of the above define on
+										  features.h/unistd.h syscall() */
+#else
+	#define _XOPEN_SOURCE_EXTENDED 1   /* solaris */
+#endif
+
+#include <time.h>
+
+#undef _XOPEN_SOURCE
+#undef _XOPEN_SOURCE_EXTENDED
+
+#include <string.h>
+#include <stdlib.h>
+#include <libxml/parser.h>
+#include "../../dprint.h"
+#include "../../sr_module.h"
+#include "pidf.h"
+
+xmlAttrPtr xmlNodeGetAttrByName(xmlNodePtr node, const char *name)
+{
+	xmlAttrPtr attr = node->properties;
+	while (attr) {
+		if (xmlStrcasecmp(attr->name, (unsigned char*)name) == 0)
+			return attr;
+		attr = attr->next;
+	}
+	return NULL;
+}
+
+char *xmlNodeGetAttrContentByName(xmlNodePtr node, const char *name)
+{
+	xmlAttrPtr attr = xmlNodeGetAttrByName(node, name);
+	if (attr)
+		return (char*)xmlNodeGetContent(attr->children);
+	else
+		return NULL;
+}
+
+xmlNodePtr xmlNodeGetChildByName(xmlNodePtr node, const char *name)
+{
+	xmlNodePtr cur = node->children;
+	while (cur) {
+		if (xmlStrcasecmp(cur->name, (unsigned char*)name) == 0)
+			return cur;
+		cur = cur->next;
+	}
+	return NULL;
+}
+
+xmlNodePtr xmlNodeGetNodeByName(xmlNodePtr node, const char *name, const char *ns)
+{
+	xmlNodePtr cur = node;
+	while (cur) {
+		xmlNodePtr match = NULL;
+		if (xmlStrcasecmp(cur->name, (unsigned char*)name) == 0) {
+			if (!ns || (cur->ns && xmlStrcasecmp(cur->ns->prefix,
+							(unsigned char*)ns) == 0))
+				return cur;
+		}
+		match = xmlNodeGetNodeByName(cur->children, name, ns);
+		if (match)
+			return match;
+		cur = cur->next;
+	}
+	return NULL;
+}
+
+char *xmlNodeGetNodeContentByName(xmlNodePtr root, const char *name,
+		const char *ns)
+{
+	xmlNodePtr node = xmlNodeGetNodeByName(root, name, ns);
+	if (node)
+		return (char*)xmlNodeGetContent(node->children);
+	else
+		return NULL;
+}
+
+xmlNodePtr xmlDocGetNodeByName(xmlDocPtr doc, const char *name, const char *ns)
+{
+	xmlNodePtr cur = doc->children;
+	return xmlNodeGetNodeByName(cur, name, ns);
+}
+
+char *xmlDocGetNodeContentByName(xmlDocPtr doc, const char *name, 
+		const char *ns)
+{
+	xmlNodePtr node = xmlDocGetNodeByName(doc, name, ns);
+	if (node)
+		return (char*)xmlNodeGetContent(node->children);
+	else
+		return NULL;
+}
+
+time_t xml_parse_dateTime(char* xml_time_str)
+{
+	struct tm tm;
+	char * p;
+	int h, m;
+	char h1, h2, m1, m2;
+	int sign= 1;
+	signed int timezone_diff= 0;
+
+	p= strptime(xml_time_str, "%F", &tm);
+	if(p== NULL)
+	{
+		printf("error: failed to parse time\n");
+		return 0;
+	}
+	p++;
+	p= strptime(p, "%T", &tm);
+	if(p== NULL)
+	{
+		printf("error: failed to parse time\n");
+		return 0;
+	}
+	
+	if(*p== '\0')
+		goto done;
+
+	if(*p== '.')
+	{
+		p++;
+		/* read the fractionar part of the seconds*/
+		while(*p!= '\0' && *p>= '0' && *p<= '9')
+		{
+			p++;
+		}
+	}
+
+	if(*p== '\0')
+		goto done;
+
+	
+	/* read time zone */
+
+	if(*p== 'Z')
+	{
+		goto done;
+	}
+
+	if(*p== '+')
+		sign= -1;
+
+	p++;
+
+	if(sscanf(p, "%c%c:%c%c", &h1, &h2, &m1, &m2) < 0) {
+		printf("error: failed to parse time\n");
+		return 0;
+	}
+	
+	h= (h1- '0')*10+ h2- '0';
+	m= (m1- '0')*10+ m2- '0';
+
+	timezone_diff= sign* ((m+ h* 60)* 60);
+
+done:
+	return (mktime(&tm) + timezone_diff);	
+}
+
+

+ 53 - 0
modules_k/presence_conference/pidf.h

@@ -0,0 +1,53 @@
+/*
+ * $Id: pidf.h 1401 2006-12-14 11:12:42Z anca_vamanu $
+ *
+ * presence module - presence server implementation
+ *
+ * Copyright (C) 2006 Voice Sistem S.R.L.
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * History:
+ * --------
+ *  2006-08-15  initial version (anca)
+ */
+
+/*! \file
+ * \brief Kamailio Presence_XML :: PIDF handling
+ * \ref pidf.c
+ * \ingroup presence_xml
+ */
+
+
+#ifndef PIDF_H
+#define PIDF_H
+
+#include "../../str.h"
+#include <libxml/parser.h>
+
+xmlNodePtr xmlNodeGetNodeByName(xmlNodePtr node, const char *name,
+															const char *ns);
+xmlNodePtr xmlDocGetNodeByName(xmlDocPtr doc, const char *name, const char *ns);
+xmlNodePtr xmlNodeGetChildByName(xmlNodePtr node, const char *name);
+
+char *xmlNodeGetNodeContentByName(xmlNodePtr root, const char *name,
+		const char *ns);
+char *xmlNodeGetAttrContentByName(xmlNodePtr node, const char *name);
+
+time_t xml_parse_dateTime(char* xml_time_str);
+
+#endif 

+ 133 - 0
modules_k/presence_conference/presence_conference.c

@@ -0,0 +1,133 @@
+/*
+ * presence_conference module - Presence Handling of "conference" events (handling conference-info+xml doc)
+ *
+ * Copyright (C) 2010 Marius Bucur
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * History:
+ * --------
+ * 2010-07-12  initial version (mariusbucur)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "../../sr_module.h"
+#include "../../dprint.h"
+#include "../../str.h"
+#include "../../parser/msg_parser.h"
+#include "../../mem/mem.h"
+#include "../presence/bind_presence.h"
+#include "add_events.h"
+#include "presence_conference.h"
+
+MODULE_VERSION
+
+/* module functions */
+static int mod_init(void);
+
+/* module variables */
+add_event_t pres_add_event;
+
+/* module parameters */
+int use_partial_states = 0;
+
+/* module mi command functions */
+static struct mi_root* conference_reset(struct mi_root* cmd, void* param);
+
+/* module exported commands */
+static cmd_export_t cmds[] =
+{
+    {0,	0, 0, 0, 0, 0}
+};
+
+/* module exported paramaters */
+static param_export_t params[] = {
+	{ "use_partial_states", INT_PARAM, &use_partial_states },
+	{0, 0, 0}
+};
+
+/* module mi commands */
+static mi_export_t mi_cmds[] = {
+	{ "conference_reset", conference_reset, 0, 0, 0},
+	{ 0, 0, 0, 0, 0 }
+};
+
+/* presence api bind structure */
+presence_api_t pres;
+
+/* module exports */
+struct module_exports exports= {
+    "presence_conference",		/* module name */
+    DEFAULT_DLFLAGS,			/* dlopen flags */
+    cmds,				/* exported functions */
+    params,				/* exported parameters */
+    0,					/* exported statistics */
+    mi_cmds,				/* exported MI functions */
+    0,					/* exported pseudo-variables */
+    0,					/* extra processes */
+    mod_init,				/* module initialization function */
+    0,					/* response handling function */
+    0,					/* destroy function */
+    0					/* per-child init function */
+};
+	
+/*
+ * init module function
+ */
+static int mod_init(void)
+{
+	bind_presence_t bind_presence;
+
+	bind_presence= (bind_presence_t)find_export("bind_presence", 1,0);
+	if (!bind_presence) {
+		LM_ERR("cannot find bind_presence\n");
+		return -1;
+	}
+	if (bind_presence(&pres) < 0) {
+		LM_ERR("cannot bind to presence module\n");
+		return -1;
+	}
+
+	pres_add_event = pres.add_event;
+	if (add_event == NULL) {
+		LM_ERR("could not import add_event function\n");
+		return -1;
+	}
+	if(conference_add_events() < 0) {
+		LM_ERR("failed to add conference-info events\n");
+		return -1;		
+	}	
+    
+    return 0;
+}
+
+
+/* module mi command functions */
+
+//presence_conference reset mi command
+static struct mi_root* conference_reset(struct mi_root* cmd, void* param)
+{
+	LM_ERR("Conference received mi command [reason %*.s] [code %d]...\n", cmd->reason.len, cmd->reason.s, cmd->code);
+	//reset subscriptions to the event package for some presentity (conference)
+	return cmd;
+}

+ 33 - 0
modules_k/presence_conference/presence_conference.h

@@ -0,0 +1,33 @@
+/*
+ * presence_conference module - main module header file mariusbucur
+ *
+ * Copyright (C) 2007 Juha Heinanen
+ * Copyright (C) 2008 Klaus Darilion IPCom
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * History:
+ * --------
+ * 2010-07-12  initial version (mariusbucur)
+ */
+
+#ifndef _PRES_CONFERENCE_H_
+#define _PRES_CONFERENCE_H_
+
+extern add_event_t pres_add_event;
+
+#endif

+ 0 - 0
modules_k/presence_conference/publish.xml


+ 72 - 0
modules_k/presence_conference/test_framework/client.sh

@@ -0,0 +1,72 @@
+#!/bin/bash
+SLEEP_STATE=0.5
+LOCAL_IP=127.0.0.1
+ADDITIONAL_PARAMETERS="-mp 40220 -mi $LOCAL_IP -p 5068 -t u1 -i $LOCAL_IP"
+_EXPECTED_RETURN=99
+OUTPUT=" -bg "
+source functions/register.sh
+source functions/subscribe.sh
+source functions/publish.sh
+source functions/notify.sh
+event="conference"
+while [[ $# > 0 ]]; do
+        if [[ $1 == "-event" ]]; then
+                event=$2
+                shift
+        fi
+        shift
+done
+
+content_type=""
+if [[ $event == "presence" ]]; then
+        content_type="application\/pidf+xml"
+fi
+if [[ $event == "conference" ]]; then
+        content_type="application\/conference-info+xml"
+fi
+
+if [[ $content_type == "" ]]; then
+        echo unknown event: $event
+        exit 2
+fi
+clear
+while [[ true ]]; do
+
+	echo s\:subscribe \| r\:register \| p\:publish \| us\:unsubscribe
+	read opt
+	if [[ "$opt" == "r" ]]; then
+		echo enter username:
+		read username
+		register $LOCAL_IP $username &> /dev/null
+		echo registered $username
+	fi
+	if [[ "$opt" == "s" ]]; then
+		echo enter username
+		read username
+		echo enter presentity
+		read presentity
+		subscribe $event $content_type $presentity $LOCAL_IP 3600 $username  &>/dev/null
+		echo regeristered watcher $username on event:$event - for resource $presentity &> /dev/null
+	fi
+	if [[ "$opt" == "p" ]]; then
+		notify &> /dev/null
+		sleep $SLEEP_STATE
+		echo enter presentity
+		read presentity
+		publish $event $content_type $presentity $LOCAL_IP &>/dev/null
+		echo published document for event package $event - resource $presentity
+	fi
+	if [[ "$opt" == "us" ]]; then
+                echo enter username
+                read username
+                echo enter presentity
+                read presentity
+                subscribe $event $content_type $presentity $LOCAL_IP 0 $username  &>/dev/null
+                echo regeristered watcher $username on event:$event - for resource $presentity &> /dev/null
+        fi
+	sleep $SLEEP_STATE
+	killall sipp &> /dev/null
+	clear
+
+done
+

+ 53 - 0
modules_k/presence_conference/test_framework/dereg.sh

@@ -0,0 +1,53 @@
+#!/bin/bash
+SLEEP_STATE=0.5
+LOCAL_IP=127.0.0.1
+ADDITIONAL_PARAMETERS="-mp 40220 -mi $LOCAL_IP -p 5068 -t u1 -i $LOCAL_IP"
+_EXPECTED_RETURN=99
+OUTPUT=" -bg "
+source functions/register.sh
+source functions/subscribe.sh
+source functions/publish.sh
+source functions/notify.sh
+event="conference"
+while [[ $# > 0 ]]; do
+
+	if [[ $1 == "-event" ]]; then
+		event=$2
+		shift
+	fi
+	shift
+done
+
+content_type=""
+if [[ $event == "presence" ]]; then
+	content_type="application\/pidf+xml"
+fi
+if [[ $event == "conference" ]]; then
+	content_type="application\/conference-info+xml"
+fi
+
+if [[ $content_type == "" ]]; then
+	echo unknown event: $event
+	exit 2
+fi
+
+###deregister sipp
+echo deregistering sipp...
+register $LOCAL_IP sipp 0 &> /dev/null
+sleep $SLEEP_STATE
+
+###deregister conference
+echo deregistering conference...
+register $LOCAL_IP conference 0 &> /dev/null
+sleep $SLEEP_STATE
+
+###unsubscribe to conference
+echo unsubscribing to conference event package...
+subscribe $event "application\/conference-info+xml" conference $LOCAL_IP 0 sipp &> /dev/null
+sleep $SLEEP_STATE
+
+###kill remaining sipp bg processes
+sleep $SLEEP_STATE;sleep $SLEEP_STATE;
+killall sipp &> /dev/null
+
+echo all done!!

+ 8 - 0
modules_k/presence_conference/test_framework/functions/notify.sh

@@ -0,0 +1,8 @@
+#!/bin/bash
+
+function notify {
+	sipp -sf xml/notify.xml $ADDITIONAL_PARAMETERS -m 8 -bg
+	if [[ $? != 99 ]]; then
+		echo sipp notify went wrong!!
+	fi
+}

+ 23 - 0
modules_k/presence_conference/test_framework/functions/publish.sh

@@ -0,0 +1,23 @@
+#!/bin/bash
+function publish {
+	if [[ $# < 4 ]]; then
+		echo not enough parameters for subscribe \(event content_type user and host\)
+		return 2
+	fi
+	event=$1
+	content_type=$2
+	presentity=$3
+	host=$4
+	tmpfile=`mktemp /tmp/subs.XXXXXXXX`
+	cat xml/publish.xml > $tmpfile
+	sed s/"\[event\]"/"$event"/ -i $tmpfile
+	sed s/"\[content-type\]"/"$content_type"/ -i $tmpfile
+	sed s/"\[presentity\]"/"$presentity"/ -i $tmpfile
+	rand_value=`head /dev/urandom | md5sum | cut -d ' ' -f 1`
+	sed s/"\[rand_tag\]"/"$rand_value"/g -i $tmpfile
+	sipp $ADDITIONAL_PARAMETERS -p 5260 -mp 5262 -sf $tmpfile $host -m 1 $OUTPUT
+	if [[ $? != $_EXPECTED_RETURN ]]; then
+		echo sipp publish went wrong!!
+	fi
+	return 0
+}

+ 22 - 0
modules_k/presence_conference/test_framework/functions/register.sh

@@ -0,0 +1,22 @@
+#!/bin/bash
+function register {
+	if [[ $# < 2 ]]; then
+		echo register must take parameters: host, username, expiry
+		return 2
+	fi
+	expiry=$3
+	if [[ ! $expiry ]]; then
+		expiry=3600
+	fi
+	tmpfile=`mktemp /tmp/tmp.XXXXXXXX`
+	cat xml/register.xml > $tmpfile
+	sed s/"\[expiry\]"/"$expiry"/g -i $tmpfile
+	sed s/"\[username\]"/"$2"/g -i $tmpfile
+	sipp $ADDITIONAL_PARAMETERS -sf $tmpfile "$1" -m 1 $OUTPUT
+	result=$?
+	if [[ $result != $_EXPECTED_RETURN ]]; then
+		echo sipp went wrong while registering
+		return 2
+	fi
+	return 0
+}

+ 25 - 0
modules_k/presence_conference/test_framework/functions/subscribe.sh

@@ -0,0 +1,25 @@
+#!/bin/bash
+function subscribe {
+	if [[ $# < 6 ]]; then
+		echo not enough parameters for subscribe \(event content_type user host expiry and username\)
+		return 2
+	fi
+	event=$1
+	content_type=$2
+	presentity=$3
+	host=$4
+	tmpfile=`mktemp /tmp/subs.XXXXXXXX`
+	cat xml/subscribe.xml > $tmpfile
+	sed s/"\[event\]"/"$event"/ -i $tmpfile
+	sed s/"\[content-type\]"/"$content_type"/ -i $tmpfile
+	sed s/"\[presentity\]"/"$presentity"/ -i $tmpfile
+	sed s/"\[username\]"/"$6"/ -i $tmpfile
+	rand_value=`head /dev/urandom | md5sum | cut -d ' ' -f 1`
+	sed s/"\[rand_tag\]"/"$rand_value"/g -i $tmpfile
+	sed s/"\[expiry\]"/"$5"/g -i $tmpfile
+	sipp $ADDITIONAL_PARAMETERS -sf $tmpfile $host -m 1 $OUTPUT
+	if [[ $? != $_EXPECTED_RETURN ]]; then
+		echo sipp subscribe went wrong!!
+	fi
+	return 0
+}

+ 0 - 0
modules_k/presence_conference/test_framework/publish.xml


+ 63 - 0
modules_k/presence_conference/test_framework/scen.sh

@@ -0,0 +1,63 @@
+#!/bin/bash
+SLEEP_STATE=0.5
+LOCAL_IP=127.0.0.1
+ADDITIONAL_PARAMETERS="-mp 40220 -mi $LOCAL_IP -p 5068 -t u1 -i $LOCAL_IP"
+_EXPECTED_RETURN=99
+OUTPUT=" -bg "
+source functions/register.sh
+source functions/subscribe.sh
+source functions/publish.sh
+source functions/notify.sh
+event="conference"
+while [[ $# > 0 ]]; do
+	if [[ $1 == "-event" ]]; then
+		event=$2
+		shift
+	fi
+	shift
+done
+
+content_type=""
+if [[ $event == "presence" ]]; then
+	content_type="application\/pidf+xml"
+fi
+if [[ $event == "conference" ]]; then
+	content_type="application\/conference-info+xml"
+fi
+
+if [[ $content_type == "" ]]; then
+	echo unknown event: $event
+	exit 2
+fi
+
+###register sipp
+echo registering sipp...
+register $LOCAL_IP sipp &> /dev/null
+sleep $SLEEP_STATE
+
+###register conference
+echo registering conference...
+register $LOCAL_IP conference &> /dev/null
+sleep $SLEEP_STATE
+
+###subscribe to conference
+echo subscribing to conference event package...
+subscribe $event "application\/conference-info+xml" conference $LOCAL_IP 3600 sipp &> /dev/null
+sleep $SLEEP_STATE
+
+###receive notify after publishing
+echo receiving notify from publish...
+notify &> /dev/null
+sleep $SLEEP_STATE
+
+###publish conference-info+xml document
+echo publishing event state...
+publish $event "application\/conference-info+xml" conference $LOCAL_IP &> /dev/null
+sleep $SLEEP_STATE
+
+###kill remaining sipp bg processes
+sleep $SLEEP_STATE;sleep $SLEEP_STATE;
+killall sipp &> /dev/null
+
+echo all done!!
+./dereg.sh

+ 17 - 0
modules_k/presence_conference/test_framework/xml/notify.xml

@@ -0,0 +1,17 @@
+<?xml encoding="UTF-8"?>
+<scenario name="subscribe_conference_event">
+	<recv request="NOTIFY"/>
+	        <send>
+		                        <![CDATA[
+SIP/2.0 200 OK
+[last_Via]
+[last_To]
+[last_From]
+Call-ID: [call_id]
+[last_Cseq]
+Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS
+Contact: <sip:sipp@[local_ip]:[local_port];transport=[transport]>
+Content-Length: 0
+		                        ]]>
+		</send>
+</scenario>

+ 103 - 0
modules_k/presence_conference/test_framework/xml/publish.xml

@@ -0,0 +1,103 @@
+<?xml encoding="UTF-8"?>
+<scenario name="subscribe_conference_event">
+        <send>
+	                <![CDATA[
+PUBLISH sip:[presentity]@[remote_ip] SIP/2.0
+Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+From: sip:[presentity]@[local_ip]:[local_port];tag=[rand_tag]
+To: sip:[presentity]@[remote_ip]
+Max-Forwards: 70
+Contact: <sip:[presentity]@[local_ip]:[local_port];transport=[transport]>
+Call-ID: [call_id]
+CSeq: 1 PUBLISH
+Event: [event]
+Expires: 3600
+Content-type: [content-type]
+Content-Length: [len]
+
+<?xml version="1.0" encoding="UTF-8"?>
+   <conference-info
+    xmlns="urn:ietf:params:xml:ns:conference-info"
+    entity="sips:[email protected]"
+    state="full" version="1">
+   <!--
+     CONFERENCE INFO
+   -->
+    <conference-description>
+     <subject>Agenda: This month's goals</subject>
+      <service-uris>
+       <entry>
+        <uri>http://sharepoint/salesgroup/</uri>
+        <purpose>web-page</purpose>
+       </entry>
+      </service-uris>
+     </conference-description>
+   <!--
+      CONFERENCE STATE
+   -->
+    <conference-state>
+     <user-count>33</user-count>
+    </conference-state>
+   <!--
+     USERS
+   -->
+    <users>
+     <user entity="sip:[email protected]" state="full">
+      <display-text>Bob Hoskins</display-text>
+   <!--
+     ENDPOINTS
+   -->
+      <endpoint entity="sip:[email protected]">
+       <display-text>Bob's Laptop</display-text>
+       <status>disconnected</status>
+       <disconnection-method>departed</disconnection-method>
+       <disconnection-info>
+        <when>2005-03-04T20:00:00Z</when>
+        <reason>bad voice quality</reason>
+        <by>sip:[email protected]</by>
+       </disconnection-info>
+   <!--
+     MEDIA
+   -->
+       <media id="1">
+        <display-text>main audio</display-text>
+        <type>audio</type>
+        <label>34567</label>
+        <src-id>432424</src-id>
+        <status>sendrecv</status>
+       </media>
+      </endpoint>
+     </user>
+   <!--
+     USER
+   -->
+     <user entity="sip:[email protected]" state="full">
+      <display-text>Alice</display-text>
+   <!--
+     ENDPOINTS
+   -->
+      <endpoint entity="sip:[email protected];grid=433kj4j3u">
+       <status>connected</status>
+       <joining-method>dialed-out</joining-method>
+       <joining-info>
+        <when>2005-03-04T20:00:00Z</when>
+        <by>sip:[email protected]</by>
+       </joining-info>
+   <!--
+     MEDIA
+   -->
+       <media id="1">
+        <display-text>main audio</display-text>
+        <type>audio</type>
+        <label>34567</label>
+        <src-id>534232</src-id>
+        <status>sendrecv</status>
+       </media>
+      </endpoint>
+     </user>
+    </users>
+   </conference-info>
+			]]>
+	</send>
+	<recv response="200"/>
+</scenario>

+ 18 - 0
modules_k/presence_conference/test_framework/xml/register.xml

@@ -0,0 +1,18 @@
+<?xml encoding="UTF-8"?>
+<scenario name="register_uac">
+        <send>
+	                <![CDATA[
+REGISTER sip:[remote_ip] SIP/2.0
+Via: SIP/2.0/[transport] [local_ip]:[local_port]
+From: [username] <sip:[username]@[local_ip]:[local_port]>;tag=[call_number]
+To: [username] <sip:[username]@[local_ip]:[local_port]>
+Max-Forwards: 70
+CSeq: 1 REGISTER
+Call-ID: [call_id]
+Contact: <sip:[username]@[local_ip]:[local_port];transport=[transport]>
+Expires: [expiry]
+Content-Length: 0
+			]]>
+	</send>
+	<recv response="200"/>
+</scenario>

+ 35 - 0
modules_k/presence_conference/test_framework/xml/subscribe.xml

@@ -0,0 +1,35 @@
+<?xml encoding="UTF-8"?>
+<scenario name="subscribe_conference_event">
+        <send>
+	                <![CDATA[
+SUBSCRIBE sip:[presentity]@[remote_ip] SIP/2.0
+Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+From: sip:[username]@[local_ip]:[local_port];tag=[rand_tag]
+To: sip:[presentity]@[remote_ip]
+Max-Forwards: 70
+Contact: <sip:[username]@[local_ip]:[local_port];transport=[transport]>
+Call-ID: [call_id]
+CSeq: 1 SUBSCRIBE
+Event: [event]
+Expires: [expiry]
+Accept: [content-type]
+Content-Length:  0
+			]]>
+	</send>
+	<recv response="202"/>
+	<recv request="NOTIFY">
+	</recv>
+	<send>
+			<![CDATA[
+SIP/2.0 200 OK
+[last_Via]
+To: <sip:[username]@[local_ip]>;tag=[rand_tag]
+From: <sip:[presentity]@[remote_ip]>[peer_tag_param]
+Call-ID: [call_id]
+CSeq: 1 NOTIFY
+Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS
+Contact: <sip:[username]@[local_ip]:[local_port];transport=[transport]>
+Content-Length: 0
+			]]>
+	</send>
+</scenario>