r3347 - in trunk: libmnetutil libmnetutil/include libmnetutil/include/libmnetutil libmnetutil/source libmutil libmutil/include libmutil/include/libmutil libmutil/source

mikaelsv at minisip.org mikaelsv at minisip.org
Sat Jun 30 15:28:33 CEST 2007


Author: mikaelsv
Date: 2007-06-30 15:28:33 +0200 (Sat, 30 Jun 2007)
New Revision: 3347

Added:
   trunk/libmnetutil/include/libmnetutil/DirectorySet.h
   trunk/libmnetutil/include/libmnetutil/DirectorySetItem.h
   trunk/libmnetutil/source/DirectorySet.cxx
   trunk/libmnetutil/source/DirectorySetItem.cxx
   trunk/libmutil/include/libmutil/CacheItem.h
   trunk/libmutil/source/CacheItem.cxx
Modified:
   trunk/libmnetutil/Makefile.am
   trunk/libmnetutil/include/Makefile.am
   trunk/libmutil/Makefile.am
   trunk/libmutil/include/Makefile.am
Log:
Added a few classes that will aid in the future development of an information cache:

* CacheItem (libmutil) is a "base class" for all classes that represent some kind of 
  cachable information. Basically any type of information qualifies as "cachable", but
  primarily certificates, CRLs and directory service locations are the most attractive
  to cache as it would reduce the network communication.

* DirectorySetItem (libmnetutil) represents information about a directory service.
  This class extends CacheItem.

* DirectorySet (libmnetutil) contains information about multiple directories. The 
  class is almost identical to CertificateSet and provides the same functionality.



Modified: trunk/libmnetutil/Makefile.am
===================================================================
--- trunk/libmnetutil/Makefile.am	2007-06-29 16:46:52 UTC (rev 3346)
+++ trunk/libmnetutil/Makefile.am	2007-06-30 13:28:33 UTC (rev 3347)
@@ -65,7 +65,9 @@
 		    source/HttpDownloader.cxx \
 		    source/FileUrl.cxx \
 		    source/FileDownloaderException.cxx \
-		    source/FileDownloader.cxx
+		    source/FileDownloader.cxx \
+		    source/DirectorySet.cxx \
+		    source/DirectorySetItem.cxx
 
 # maintainer rules
 ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}

Modified: trunk/libmnetutil/include/Makefile.am
===================================================================
--- trunk/libmnetutil/include/Makefile.am	2007-06-29 16:46:52 UTC (rev 3346)
+++ trunk/libmnetutil/include/Makefile.am	2007-06-30 13:28:33 UTC (rev 3347)
@@ -30,7 +30,9 @@
 			libmnetutil/HttpDownloader.h \
 			libmnetutil/FileUrl.h \
 			libmnetutil/FileDownloaderException.h \
-			libmnetutil/FileDownloader.h
+			libmnetutil/FileDownloader.h \
+			libmnetutil/DirectorySet.h \
+			libmnetutil/DirectorySetItem.h
 
 noinst_HEADERS = 	\
 			config.h \

Added: trunk/libmnetutil/include/libmnetutil/DirectorySet.h
===================================================================
--- trunk/libmnetutil/include/libmnetutil/DirectorySet.h	                        (rev 0)
+++ trunk/libmnetutil/include/libmnetutil/DirectorySet.h	2007-06-30 13:28:33 UTC (rev 3347)
@@ -0,0 +1,148 @@
+/*
+  Copyright (C) 2007, Mikael Svensson
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/*
+ * Authors:	Mikael Svensson
+ *              Erik Eliasson <eliasson at it.kth.se>
+ *          	Johan Bilien <jobi at via.ecp.fr>
+ *          	Mikael Magnusson <mikma at users.sourceforge.net>
+ */
+
+#ifndef _DIRECTORYITEM_H_
+#define _DIRECTORYITEM_H_
+
+#include <libmnetutil/libmnetutil_config.h>
+#include <libmutil/MemObject.h>
+#include <libmutil/Mutex.h>
+
+#include <libmnetutil/DirectorySetItem.h>
+
+/**
+ * Class for managing a set of directory service information items.
+ *
+ * More or less a duplicate of the CertificateSet class.
+ *
+ * Sample code:
+ * @code
+#include <libmnetutil/DirectorySet.h>
+#include <libmnetutil/DirectorySetItem.h>
+#include <string>
+#include <list>
+#include <iostream>
+
+int main (int argc, char* argv[]) {
+	std::list<MRef<DirectorySetItem *> > items;
+	std::list<MRef<DirectorySetItem *> >::iterator allItemsIter;
+
+	DirectorySet* set = DirectorySet::create();
+
+	//CREATING THE SET
+	set->addLdap("ldap://ucd-slow.minisip.org/dc=ucd-slow,dc=minisip,dc=org", "ucd-slow.minisip.org");
+	set->addLdap("ldap://ucd-slow.minisip.org/dc=ucd-slow,dc=minisip,dc=org", "minisip.org");
+	set->addLdap("ldap://ucd-fast.ssvl.kth.se/dc=ucd-fast,dc=ssvl,dc=kth,dc=se", "ucd-fast.ssvl.kth.se");
+
+	//PRINTING THE COMPLETE SET
+	std::cout << "The complete set:" << std::endl;
+	for (allItemsIter = set->getItems().begin(); allItemsIter != set->getItems().end(); allItemsIter++) {
+		std::cout << "   " << (*allItemsIter)->getSubTree() << " is handled by " << (*allItemsIter)->getUrl() << std::endl;
+	}
+	std::cout << std::endl;
+
+
+	//SEARCHING THE SET
+	std::string patterns[] = {"kth.se", 	"minisip.org",	"minisip.org",	"ucd-fast.minisip.org",	"sunet.se"};
+	bool partialMatching[] = {true, 	false, 		true, 		true, 			false};
+	int num = 5;
+
+	for (int i=0; i < num; i++) {
+		std::cout << "Searching for directories responsible for " << patterns[i] << (partialMatching[i] ? " and sub-domains" : " but not its sub-domains") << ":" << std::endl;
+
+		items = set->findItems(patterns[i], partialMatching[i]);
+		while (!items.empty()) {
+			std::cout << "   Match: " << items.front()->getSubTree() << " URL: " << items.front()->getUrl() << std::endl;
+			items.pop_front();
+		}
+		std::cout << std::endl;
+	}
+
+
+	delete set;
+
+	return 0;
+}
+ * @endcode
+ * @author	Mikael Svensson
+ */
+class DirectorySet : public MObject {
+	public:
+		DirectorySet();
+		~DirectorySet();
+		static DirectorySet *create();
+
+		DirectorySet* clone();
+		void addLdap (std::string url, std::string subTree);
+
+		/**
+		 * Returns \em reference to the list of all directory items in the set
+		 *
+		 * @note	This function resets the internal list iterator.
+		 */
+		std::list<MRef<DirectorySetItem*> > & getItems();
+
+		/**
+		 * Returns a list of directory items matching the given sub-tree identifier.
+		 *
+		 * The second parameter sets if the whole sub-tree string should be matched or only the last
+		 * part of. This is useful if one directory item has subTree = "kth.se" and another one has
+		 * subTree = "ssvl.kth.se" and you want to retrieve both of them: then you just set the
+		 * first function parameter to "kth.se" and the second to "true".
+		 *
+		 * @note	This function does \em not return a reference variable, which getItems() do.
+		 * 		However, even though it returns a new list, each of the list items still refer
+		 * 		to the exact same items that are stored in the set (i.e. items are not cloned
+		 * 		before returned by this function).
+		 * @note	This function resets the internal list iterator.
+		 * @param	subTree			The string to search for in the \c subTree property of
+		 * 					each DirectorySetItem object in the set.
+		 * @param	endsWithIsEnough	If true (default): function returns all DirectorySetItem
+		 * 					objects where the subTree string ends with \p subTree.
+		 * 					If false: function returns only items where there is and
+		 * 					exact matching of \p subTree.
+		 */
+		std::list<MRef<DirectorySetItem*> > findItems(const std::string subTree, bool endsWithIsEnough = true);
+		MRef<DirectorySetItem*> getNext();
+
+		void initIndex();
+		void lock();
+		void unlock();
+
+		void remove (MRef<DirectorySetItem*> removedItem);
+
+		void addItem (MRef<DirectorySetItem*> item);
+
+		/**
+		 * Create directory item refering to an LDAP directory
+		 */
+		MRef<DirectorySetItem*> createItemLdap(std::string url, std::string subTree);
+
+	private:
+		std::list<MRef<DirectorySetItem*> >::iterator itemsIndex;
+		std::list<MRef<DirectorySetItem*> > items;
+		Mutex mLock;
+};
+#endif

Added: trunk/libmnetutil/include/libmnetutil/DirectorySetItem.h
===================================================================
--- trunk/libmnetutil/include/libmnetutil/DirectorySetItem.h	                        (rev 0)
+++ trunk/libmnetutil/include/libmnetutil/DirectorySetItem.h	2007-06-30 13:28:33 UTC (rev 3347)
@@ -0,0 +1,80 @@
+/*
+  Copyright (C) 2007, Mikael Svensson
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/*
+ * Authors:	Mikael Svensson
+*/
+
+#ifndef _DIRECTORYSETITEM_H_
+#define _DIRECTORYSETITEM_H_
+
+#include <libmnetutil/libmnetutil_config.h>
+#include <libmutil/CacheItem.h>
+
+#include <string>
+
+#define DIRECTORYSETITEM_TYPE_UNSPECIFIED 0
+#define DIRECTORYSETITEM_TYPE_LDAP 1
+
+/**
+ * Represents a single directory service.
+ */
+class DirectorySetItem : public CacheItem {
+	public:
+		DirectorySetItem();
+		DirectorySetItem(std::string url, std::string subTree);
+		DirectorySetItem(int32_t type, std::string url, std::string subTree);
+		DirectorySetItem(int32_t type);
+
+		int32_t getType() const;
+		std::string getUrl() const;
+		std::string getSubTree() const;
+
+		void setType(const int32_t type);
+		void setUrl(const std::string url);
+		void setSubTree(const std::string subTree);
+
+		virtual std::string getMemObjectType() const {return "DirectorySetItem";};
+
+		bool operator ==(const DirectorySetItem item2) const;
+	private:
+		/**
+		 * The type of directory refered to by the url attribute.
+		 *
+	 	 * Currently the only supported value is \c DIRECTORYSETITEM_TYPE_LDAP.
+		 */
+		int32_t type;
+
+		/**
+		 * The URL used to connect to the directory. The interpretation of the URL is
+		 * dependent on the type of directory it refers to. Therefore the URL may be
+		 * an LDAP URL, or any other type of URL, as long as Minisip knows how to deal
+		 * with it.
+		 */
+		std::string url;
+
+		/**
+		 * Specified which portion of a tree that the directory server is responsible for.
+		 *
+		 * The sub-tree specifier tells us the right-most part of the mail/SIP addresses
+		 * that the server has information about.
+		 */
+		std::string subTree;
+};
+
+#endif

Added: trunk/libmnetutil/source/DirectorySet.cxx
===================================================================
--- trunk/libmnetutil/source/DirectorySet.cxx	                        (rev 0)
+++ trunk/libmnetutil/source/DirectorySet.cxx	2007-06-30 13:28:33 UTC (rev 3347)
@@ -0,0 +1,136 @@
+/*
+  Copyright (C) 2007, Mikael Svensson
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/*
+ * Authors:	Mikael Svensson
+ *              Erik Eliasson <eliasson at it.kth.se>
+ *          	Johan Bilien <jobi at via.ecp.fr>
+ *          	Mikael Magnusson <mikma at users.sourceforge.net>
+ */
+
+#include <libmnetutil/libmnetutil_config.h>
+#include <libmutil/MemObject.h>
+
+#include <libmnetutil/DirectorySet.h>
+#include <libmutil/stringutils.h>
+
+DirectorySet::DirectorySet(){
+	itemsIndex = items.begin();
+}
+
+DirectorySet::~DirectorySet(){
+	std::list<MRef<DirectorySetItem*> >::iterator i;
+	std::list<MRef<DirectorySetItem*> >::iterator last = items.end();
+
+	items.clear();
+}
+
+DirectorySet* DirectorySet::clone(){
+	DirectorySet * db = create();
+
+	lock();
+	std::list<MRef<DirectorySetItem*> >::iterator i;
+	std::list<MRef<DirectorySetItem*> >::iterator last = items.end();
+
+	for( i = items.begin(); i != last; i++ ){
+		db->addItem( *i );
+	}
+
+	unlock();
+	return db;
+}
+
+DirectorySet* DirectorySet::create() {
+	return new DirectorySet();
+}
+
+void DirectorySet::lock(){
+	mLock.lock();
+}
+
+void DirectorySet::unlock(){
+	mLock.unlock();
+}
+
+void DirectorySet::addItem( MRef<DirectorySetItem*> item ){
+	items.push_back( item );
+	itemsIndex = items.begin();
+}
+
+MRef<DirectorySetItem*> DirectorySet::createItemLdap (std::string url, std::string subTree){
+	MRef<DirectorySetItem*> item = new DirectorySetItem(url, subTree);
+
+	return item;
+}
+
+void DirectorySet::addLdap (std::string url, std::string subTree) {
+	MRef<DirectorySetItem*> item = createItemLdap(url, subTree);
+	addItem(item);
+}
+
+void DirectorySet::remove( MRef<DirectorySetItem*> removedItem ){
+	initIndex();
+
+	while( itemsIndex != items.end() ){
+		if( **(*itemsIndex) == **removedItem ){
+			items.erase( itemsIndex );
+			initIndex();
+			return;
+		}
+		itemsIndex ++;
+	}
+	initIndex();
+}
+
+std::list<MRef<DirectorySetItem*> > &DirectorySet::getItems(){
+	return items;
+}
+std::list<MRef<DirectorySetItem*> > DirectorySet::findItems(const std::string subTree, bool endsWithIsEnough) {
+	std::list<MRef<DirectorySetItem*> > res;
+	initIndex();
+
+	while( itemsIndex != items.end() ){
+		MRef<DirectorySetItem*> item = *itemsIndex;
+		bool addThis = false;
+
+		if ((endsWithIsEnough && stringEndsWith(item->getSubTree(), subTree)) || item->getSubTree() == subTree)
+			res.push_back(item);
+
+		itemsIndex++;
+	}
+	initIndex();
+	return res;
+}
+
+
+void DirectorySet::initIndex(){
+	itemsIndex = items.begin();
+}
+
+MRef<DirectorySetItem*> DirectorySet::getNext(){
+	MRef<DirectorySetItem*> tmp;
+
+	if( itemsIndex == items.end() ){
+		itemsIndex = items.begin();
+		return NULL;
+	}
+
+	tmp = *itemsIndex;
+	itemsIndex++;
+	return tmp;
+}

Added: trunk/libmnetutil/source/DirectorySetItem.cxx
===================================================================
--- trunk/libmnetutil/source/DirectorySetItem.cxx	                        (rev 0)
+++ trunk/libmnetutil/source/DirectorySetItem.cxx	2007-06-30 13:28:33 UTC (rev 3347)
@@ -0,0 +1,59 @@
+/*
+  Copyright (C) 2007, Mikael Svensson
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/*
+ * Authors:	Mikael Svensson
+*/
+
+#include <libmnetutil/DirectorySetItem.h>
+
+DirectorySetItem::DirectorySetItem() : type(DIRECTORYSETITEM_TYPE_LDAP), url(""), subTree("") {}
+
+DirectorySetItem::DirectorySetItem(std::string url, std::string subTree) : type(DIRECTORYSETITEM_TYPE_LDAP), url(url), subTree(subTree) {}
+
+DirectorySetItem::DirectorySetItem(int32_t type, std::string url, std::string subTree) : type(type), url(url), subTree(subTree) {}
+
+DirectorySetItem::DirectorySetItem(int32_t type) : type(type), url(""), subTree("") {}
+
+bool DirectorySetItem::operator ==(const DirectorySetItem item2) const {
+	return (
+		item2.getUrl() == url &&
+		item2.getType() == type &&
+		item2.getSubTree() == subTree
+	       );
+}
+
+int32_t DirectorySetItem::getType() const {
+	return type;
+}
+std::string DirectorySetItem::getUrl() const {
+	return url;
+}
+std::string DirectorySetItem::getSubTree() const {
+	return subTree;
+}
+
+void DirectorySetItem::setType(const int32_t type) {
+	this->type = type;
+}
+void DirectorySetItem::setUrl(const std::string url) {
+	this->url = url;
+}
+void DirectorySetItem::setSubTree(const std::string subTree) {
+	this->subTree = subTree;
+}

Modified: trunk/libmutil/Makefile.am
===================================================================
--- trunk/libmutil/Makefile.am	2007-06-29 16:46:52 UTC (rev 3346)
+++ trunk/libmutil/Makefile.am	2007-06-30 13:28:33 UTC (rev 3347)
@@ -62,6 +62,7 @@
 		source/XMLParser.cxx \
 		source/MPlugin.cxx \
 		source/CircularBuffer.cxx \
+		source/CacheItem.cxx \
 		$(thread_src)
 
 # maintainer rules

Modified: trunk/libmutil/include/Makefile.am
===================================================================
--- trunk/libmutil/include/Makefile.am	2007-06-29 16:46:52 UTC (rev 3346)
+++ trunk/libmutil/include/Makefile.am	2007-06-30 13:28:33 UTC (rev 3347)
@@ -28,7 +28,8 @@
 			libmutil/MPlugin.h \
 			libmutil/libmutil_config.h \
 			libmutil/MSingleton.h \
-			libmutil/CircularBuffer.h
+			libmutil/CircularBuffer.h \
+			libmutil/CacheItem.h
 
 noinst_HEADERS = 	config.h
 

Added: trunk/libmutil/include/libmutil/CacheItem.h
===================================================================
--- trunk/libmutil/include/libmutil/CacheItem.h	                        (rev 0)
+++ trunk/libmutil/include/libmutil/CacheItem.h	2007-06-30 13:28:33 UTC (rev 3347)
@@ -0,0 +1,64 @@
+/*
+  Copyright (C) 2007, Mikael Svensson
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/*
+ * Authors:	Mikael Svensson
+*/
+
+#ifndef _CACHEITEM_H_
+#define _CACHEITEM_H_
+
+#include <libmutil/libmutil_config.h>
+#include <libmutil/MemObject.h>
+
+#include <time.h>
+
+/**
+ * Represents a single item in a cache.
+ *
+ * This class is very generic by design and only contains properties that can be assumed
+ * to be appropriate for any kind of cachable object. When implementing a cache that
+ * can contain multiple types of objects all those "cachable objects" may inherit from this
+ * class in order to provide some kind of uniformity.
+ *
+ * A class responsible for maintaining the entire cache by periodically removing old items
+ * can easily use the same code to scan all cached items as they all have the same
+ * basic properies, the properties defined in by the CacheItem class.
+ *
+ * @todo	Add property for "associated file path", but make sure it is not a mandatory
+ * 		property as cached items not necessarily have anything to do with actual files.
+ */
+class LIBMUTIL_API CacheItem : public MObject {
+	public:
+		CacheItem();
+
+		time_t getCacheDate() const;
+		time_t getValidFrom() const;
+		time_t getValidUntil() const;
+
+		void setCacheDate(const time_t date);
+		void setValidFrom(const time_t date);
+		void setValidUntil(const time_t date);
+
+		virtual std::string getMemObjectType() const {return "CacheItem";};
+	private:
+		time_t cacheDate;
+		time_t validFrom;
+		time_t validUntil;
+};
+#endif

Added: trunk/libmutil/source/CacheItem.cxx
===================================================================
--- trunk/libmutil/source/CacheItem.cxx	                        (rev 0)
+++ trunk/libmutil/source/CacheItem.cxx	2007-06-30 13:28:33 UTC (rev 3347)
@@ -0,0 +1,52 @@
+/*
+  Copyright (C) 2007, Mikael Svensson
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/*
+ * Authors:	Mikael Svensson
+*/
+
+#include <libmutil/CacheItem.h>
+
+CacheItem::CacheItem() {
+	cacheDate = time(NULL);
+	if (-1 == cacheDate)
+		cacheDate = 0;
+	validFrom = 0;
+	validUntil = 0;
+}
+
+time_t CacheItem::getCacheDate() const {
+	return cacheDate;
+}
+
+time_t CacheItem::getValidFrom() const {
+	return validFrom;
+}
+time_t CacheItem::getValidUntil() const {
+	return validUntil;
+}
+
+void CacheItem::setCacheDate(const time_t date) {
+	cacheDate = date;
+}
+void CacheItem::setValidFrom(const time_t date) {
+	validFrom = date;
+}
+void CacheItem::setValidUntil(const time_t date) {
+	validUntil = date;
+}



More information about the Minisip-devel mailing list