Prechádzať zdrojové kódy

lib/cds: relocated to archive

Daniel-Constantin Mierla 9 mesiacov pred
rodič
commit
f0cd5beef2
95 zmenil súbory, kde vykonal 7146 pridanie a 0 odobranie
  1. 2 0
      src/lib/cds/.cvsignore
  2. 42 0
      src/lib/cds/ChangeLog
  3. 20 0
      src/lib/cds/Makefile
  4. 12 0
      src/lib/cds/Makefile.nonser
  5. 117 0
      src/lib/cds/base64.c
  6. 37 0
      src/lib/cds/base64.h
  7. 60 0
      src/lib/cds/cds.c
  8. 78 0
      src/lib/cds/cds.h
  9. 32 0
      src/lib/cds/dbid.c
  10. 49 0
      src/lib/cds/dbid.h
  11. 4 0
      src/lib/cds/doc/Makefile
  12. 53 0
      src/lib/cds/doc/cds.xml
  13. 50 0
      src/lib/cds/doc/cds_free.xml
  14. 46 0
      src/lib/cds/doc/cds_free_ptr.xml
  15. 52 0
      src/lib/cds/doc/cds_malloc.xml
  16. 46 0
      src/lib/cds/doc/cds_malloc_ptr.xml
  17. 46 0
      src/lib/cds/doc/cds_mutex_destroy.xml
  18. 45 0
      src/lib/cds/doc/cds_mutex_init.xml
  19. 46 0
      src/lib/cds/doc/cds_mutex_lock.xml
  20. 41 0
      src/lib/cds/doc/cds_mutex_t.xml
  21. 46 0
      src/lib/cds/doc/cds_mutex_unlock.xml
  22. 64 0
      src/lib/cds/doc/create_message.xml
  23. 63 0
      src/lib/cds/doc/create_message_ex.xml
  24. 49 0
      src/lib/cds/doc/destroy_sstream.xml
  25. 77 0
      src/lib/cds/doc/dstr_append.xml
  26. 74 0
      src/lib/cds/doc/dstr_get_data.xml
  27. 55 0
      src/lib/cds/doc/dstr_init.xml
  28. 21 0
      src/lib/cds/doc/dstring.xml
  29. 103 0
      src/lib/cds/doc/dstring_t.xml
  30. 51 0
      src/lib/cds/doc/free_message.xml
  31. 55 0
      src/lib/cds/doc/get_serialized_sstream.xml
  32. 56 0
      src/lib/cds/doc/init_input_sstream.xml
  33. 55 0
      src/lib/cds/doc/init_message_ex.xml
  34. 55 0
      src/lib/cds/doc/init_output_sstream.xml
  35. 50 0
      src/lib/cds/doc/is_msg_queue_empty.xml
  36. 39 0
      src/lib/cds/doc/memory.xml
  37. 72 0
      src/lib/cds/doc/mq_message_t.xml
  38. 36 0
      src/lib/cds/doc/msg_queue.xml
  39. 54 0
      src/lib/cds/doc/msg_queue_destroy.xml
  40. 51 0
      src/lib/cds/doc/msg_queue_init.xml
  41. 55 0
      src/lib/cds/doc/msg_queue_init_ex.xml
  42. 43 0
      src/lib/cds/doc/msg_queue_t.xml
  43. 53 0
      src/lib/cds/doc/pop_message.xml
  44. 60 0
      src/lib/cds/doc/push_message.xml
  45. 36 0
      src/lib/cds/doc/serialization.xml
  46. 59 0
      src/lib/cds/doc/serialize_char.xml
  47. 59 0
      src/lib/cds/doc/serialize_int.xml
  48. 59 0
      src/lib/cds/doc/serialize_str.xml
  49. 59 0
      src/lib/cds/doc/serialize_uchar.xml
  50. 59 0
      src/lib/cds/doc/serialize_uint.xml
  51. 71 0
      src/lib/cds/doc/set_data_destroy_function.xml
  52. 28 0
      src/lib/cds/doc/sstr.xml
  53. 53 0
      src/lib/cds/doc/sstream_get.xml
  54. 58 0
      src/lib/cds/doc/sstream_get_str.xml
  55. 57 0
      src/lib/cds/doc/sstream_get_str_ex.xml
  56. 55 0
      src/lib/cds/doc/sstream_put.xml
  57. 53 0
      src/lib/cds/doc/sstream_put_str.xml
  58. 53 0
      src/lib/cds/doc/sstream_put_zt.xml
  59. 118 0
      src/lib/cds/doc/sstream_t.xml
  60. 44 0
      src/lib/cds/doc/str_clear.xml
  61. 65 0
      src/lib/cds/doc/str_dup.xml
  62. 44 0
      src/lib/cds/doc/str_free.xml
  63. 44 0
      src/lib/cds/doc/str_free_content.xml
  64. 84 0
      src/lib/cds/doc/str_other.xml
  65. 48 0
      src/lib/cds/doc/str_t.xml
  66. 23 0
      src/lib/cds/doc/sync.xml
  67. 226 0
      src/lib/cds/dstring.c
  68. 153 0
      src/lib/cds/dstring.h
  69. 250 0
      src/lib/cds/hash_table.c
  70. 96 0
      src/lib/cds/hash_table.h
  71. 64 0
      src/lib/cds/list.h
  72. 70 0
      src/lib/cds/logger.h
  73. 127 0
      src/lib/cds/memory.c
  74. 161 0
      src/lib/cds/memory.h
  75. 238 0
      src/lib/cds/msg_queue.c
  76. 196 0
      src/lib/cds/msg_queue.h
  77. 55 0
      src/lib/cds/ptr_vector.c
  78. 42 0
      src/lib/cds/ptr_vector.h
  79. 91 0
      src/lib/cds/ref_cntr.c
  80. 162 0
      src/lib/cds/ref_cntr.h
  81. 131 0
      src/lib/cds/rr_serialize.c
  82. 17 0
      src/lib/cds/rr_serialize.h
  83. 93 0
      src/lib/cds/ser_profile.c
  84. 48 0
      src/lib/cds/ser_profile.h
  85. 288 0
      src/lib/cds/serialize.c
  86. 91 0
      src/lib/cds/serialize.h
  87. 87 0
      src/lib/cds/simple_profile.c
  88. 52 0
      src/lib/cds/simple_profile.h
  89. 158 0
      src/lib/cds/sip_utils.c
  90. 31 0
      src/lib/cds/sip_utils.h
  91. 367 0
      src/lib/cds/sstr.c
  92. 170 0
      src/lib/cds/sstr.h
  93. 46 0
      src/lib/cds/sync.h
  94. 127 0
      src/lib/cds/vector.c
  95. 65 0
      src/lib/cds/vector.h

+ 2 - 0
src/lib/cds/.cvsignore

@@ -0,0 +1,2 @@
+libser_cds.so.*
+

+ 42 - 0
src/lib/cds/ChangeLog

@@ -0,0 +1,42 @@
+2007-01-18
+	* added functions to return serialized stream into existing buffer
+
+...
+
+2006-11-06
+	* bug correction - output of get_pres_rules initialized - reported by Bogdan
+
+2006-09-01
+	* corrected memory leaks in route serialization
+	* str_dup separated to macro and implementation function -> better for
+	debugging and memory leak search
+
+2006-08-08
+	* added functions for rr_t serialization/deserialization
+
+2006-06-29
+	* added function has_to_tag common for more presence modules
+
+2006-06-28
+	* optimalization of dstring operations (internal buffers allocated in PKG
+	memory, some functions changed to macros, added function dstr_get_str_pkg)
+	* some str functions changed to macros
+
+2006-06-23
+	* added function requires_extension
+
+2006-06-22
+	* added function supports_extension
+
+2006-06-21
+	* corrected bug in get_expiration_value (result was always -1/1)
+	* is_terminating_notify changed to use Subscription-State parser
+
+2006-06-13
+	* added few common SIP/SER functions into sip_utils.h
+	* added functions for traversing hash table
+
+2006-05-11
+	* added changelog
+	* added "simple profiling" capability (need to call PROF_START and
+	PROF_STOP macros in profiled routine)

+ 20 - 0
src/lib/cds/Makefile

@@ -0,0 +1,20 @@
+#
+# example library makefile
+#
+
+include ../../Makefile.defs
+auto_gen=
+NAME:=ser_cds
+MAJOR_VER=0
+MINOR_VER=1
+BUGFIX_VER=0
+DEFS+=-DSER
+INCLUDES= -I$(CURDIR)/.. -I$(CURDIR)/../..
+LIBS=
+
+ifeq ($(OS), darwin)
+	LIB_LDFLAGS+= -flat_namespace -undefined suppress
+endif
+
+include ../../Makefile.libs
+

+ 12 - 0
src/lib/cds/Makefile.nonser

@@ -0,0 +1,12 @@
+DEFS     += 
+INCLUDES +=
+LIBS     +=
+
+# name of result executable or library
+NAME = cds
+
+# TYPE=lib => shared or static library, executable otherwise
+TYPE = lib
+
+include ../Makefile.defs
+

+ 117 - 0
src/lib/cds/base64.c

@@ -0,0 +1,117 @@
+/*
+ * base64 encoding / decoding
+ *
+ * $Id$
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+void base64decode(char *src_buf, int src_len, char *tgt_buf, int *tgt_len)
+{
+	int pos, i, n;
+	unsigned char c[4];
+	for(pos = 0, i = 0, *tgt_len = 0; pos < src_len; pos++) {
+		if(src_buf[pos] >= 'A' && src_buf[pos] <= 'Z')
+			c[i] = src_buf[pos] - 65; /* <65..90>  --> <0..25> */
+		else if(src_buf[pos] >= 'a' && src_buf[pos] <= 'z')
+			c[i] = src_buf[pos] - 71; /* <97..122>  --> <26..51> */
+		else if(src_buf[pos] >= '0' && src_buf[pos] <= '9')
+			c[i] = src_buf[pos] + 4; /* <48..56>  --> <52..61> */
+		else if(src_buf[pos] == '+')
+			c[i] = 62;
+		else if(src_buf[pos] == '/')
+			c[i] = 63;
+		else /* '=' */
+			c[i] = 64;
+		i++;
+		if(pos == src_len - 1) {
+			while(i < 4) {
+				c[i] = 64;
+				i++;
+			}
+		}
+		if(i == 4) {
+			if(c[0] == 64)
+				n = 0;
+			else if(c[2] == 64)
+				n = 1;
+			else if(c[3] == 64)
+				n = 2;
+			else
+				n = 3;
+			switch(n) {
+				case 3:
+					tgt_buf[*tgt_len + 2] = (char)(((c[2] & 0x03) << 6) | c[3]);
+					/* no break */
+				case 2:
+					tgt_buf[*tgt_len + 1] =
+							(char)(((c[1] & 0x0F) << 4) | (c[2] >> 2));
+					/* no break */
+				case 1:
+					tgt_buf[*tgt_len + 0] = (char)((c[0] << 2) | (c[1] >> 4));
+					break;
+			}
+			i = 0;
+			*tgt_len += n;
+		}
+	}
+}
+
+void base64encode(
+		char *src_buf, int src_len, char *tgt_buf, int *tgt_len, int quoted)
+{
+	static char code64[64 + 1] =
+			"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+	int pos;
+	for(pos = 0, *tgt_len = 0; pos < src_len; pos += 3, *tgt_len += 4) {
+		tgt_buf[*tgt_len + 0] = code64[(unsigned char)src_buf[pos + 0] >> 2];
+		tgt_buf[*tgt_len + 1] =
+				code64[(((unsigned char)src_buf[pos + 0] & 0x03) << 4)
+						| ((pos + 1 < src_len)
+										? ((unsigned char)src_buf[pos + 1] >> 4)
+										: 0)];
+		if(pos + 1 < src_len)
+			tgt_buf[*tgt_len + 2] =
+					code64[(((unsigned char)src_buf[pos + 1] & 0x0F) << 2)
+							| ((pos + 2 < src_len) ? (
+									   (unsigned char)src_buf[pos + 2] >> 6)
+												   : 0)];
+		else {
+			if(!quoted)
+				(*tgt_len)--;
+			else
+				/* this data is going to be quoted */
+				tgt_buf[*tgt_len + 2] = '=';
+		}
+		if(pos + 2 < src_len)
+			tgt_buf[*tgt_len + 3] =
+					code64[(unsigned char)src_buf[pos + 2] & 0x3F];
+		else {
+			if(!quoted)
+				(*tgt_len)--;
+			else
+				tgt_buf[*tgt_len + 3] = '=';
+		}
+	}
+}

+ 37 - 0
src/lib/cds/base64.h

@@ -0,0 +1,37 @@
+/*
+ * base64 encoding / decoding
+ *
+ * $Id$
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef base64_h
+#define base64_h
+
+void base64decode(char *src_buf, int src_len, char *tgt_buf, int *tgt_len);
+void base64encode(
+		char *src_buf, int src_len, char *tgt_buf, int *tgt_len, int quoted);
+
+#endif

+ 60 - 0
src/lib/cds/cds.c

@@ -0,0 +1,60 @@
+#include <cds/cds.h>
+#include <cds/memory.h>
+#include <cds/sync.h>
+#include <cds/logger.h>
+
+#if 0
+
+typedef struct {
+	int init_cnt;
+} init_data_t;
+
+static init_data_t *init = NULL;
+
+/* these functions are internal and thus are not presented in headers !*/
+int reference_counter_initialize();
+void reference_counter_cleanup();
+
+int cds_initialize()
+{
+	int res = 0;
+
+	/* initialization should be called from one process/thread
+	 * it is not synchronized because it is impossible ! */
+	if (!init) {
+		init = (init_data_t*)cds_malloc(sizeof(init_data_t));
+		if (!init) return -1;
+		init->init_cnt = 0;
+	}
+
+	if (init->init_cnt > 0) { /* already initialized */
+		init->init_cnt++;
+		return 0;
+	}
+	else {
+		DEBUG_LOG("init the content\n");
+
+		/* !!! put the real initialization here !!! */
+		res = reference_counter_initialize();
+	}
+
+	if (res == 0) init->init_cnt++;
+	return res;
+}
+
+void cds_cleanup()
+{
+	if (init) {
+		if (--init->init_cnt == 0) {
+			DEBUG_LOG("cleaning the content\n");
+
+			/* !!! put the real destruction here !!! */
+			reference_counter_cleanup();
+
+			cds_free(init);
+			init = NULL;
+		}
+	}
+}
+
+#endif

+ 78 - 0
src/lib/cds/cds.h

@@ -0,0 +1,78 @@
+#ifndef __CDS_H
+#define __CDS_H
+
+/** \defgroup cds CDS library - Common Data Structures
+ *
+ * This library contains many useful functions and data structures. It is
+ possible to use it with Sip Express Router (SER) or without it. In the first
+ case it is able to use some internal SER's data types like strings.
+ *
+ * \section cds_conventions Conventions
+ *  - data types (structures, enums, ...) have their names with suffix \c _t
+ *  (\c str_t, \c dstring_t, ...)
+ *  - many functions have prefix according to data structure on which are
+ *  operating (like dstr_append which operates on dstring_t data structure)
+ *  - most functions return 0 as successful result and nonzero value as error
+ *
+ * \section cds_dependencies Dependencies
+ * This library depends only on standard C libraries and needs no other
+ * external libraries.
+ *
+ * \section cds_ser_usage Usage with SER
+ * There can be problems with using shared libraries on different platforms.
+ * Currently supported solution is that user must supply LD_LIBRARY_PATH
+ * (or something similar on his OS) with the path to the library before
+ * starting SER with modules needed the library.
+ *
+ * \section cds_nonser_usage Usage without SER
+ * The library can be compiled without dependencies on SER and can be linked
+ * to whatever program as any other dynamic library. This style of usage is
+ * probably used only when debugging problems which is hard to find with SER
+ * (outside of SER is possible to use tools like Valgrind) and for author's
+ * little programs and need not to be documented more... ;-)
+ *
+ * \par History
+ * There were following reasons to introduce this library:
+ *  - many duplicated functions in modules (copy&pasted between modules)
+ *  without touching SER's core
+ *  - possibility to debug programs outside of SER due to its simplicity
+ *  and many useful tools
+ *
+ * @{ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if 0
+/* not used */
+
+/** \defgroup cds_init Initialization/destruction
+ * Library needs to be initialized before using it and
+ * un-initialized after it is not used more. Use \ref cds_initialize and
+ * \ref cds_cleanup for this purpose.
+ * @{ */
+
+/** Initializes CDS library.
+ *
+ * Currently initializes reference counter which is experimental and
+ * probably will be removed in the future because seems to be rather
+ * useless here. */
+int cds_initialize();
+
+/** Cleans up after CDS. After calling this function can't be called
+ * reference counter functions. */
+void cds_cleanup();
+
+#endif
+
+	/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif

+ 32 - 0
src/lib/cds/dbid.c

@@ -0,0 +1,32 @@
+#include <cds/dbid.h>
+#include <cds/logger.h>
+#include <time.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+
+void generate_dbid_ptr(dbid_t dst, void *data_ptr)
+{
+	/* TODO: add cluster distinctive member */
+	snprintf(dst, MAX_DBID_LEN, "%px%xx%x", data_ptr, (int)time(NULL), rand());
+}
+
+#ifdef SER
+
+/* only for SER (not for apps with threads) */
+void generate_dbid(dbid_t dst)
+{
+	static int cntr = 0;
+	static pid_t my_pid = -1;
+
+	if(my_pid < 0) {
+		my_pid = getpid();
+	}
+
+	/* TODO: add cluster distinctive member */
+	snprintf(dst, MAX_DBID_LEN, "%xy%xy%xy%x", my_pid, cntr++, (int)time(NULL),
+			rand());
+}
+
+#endif

+ 49 - 0
src/lib/cds/dbid.h

@@ -0,0 +1,49 @@
+#ifndef __DBID_H
+#define __DBID_H
+
+/* functions and structures for generating unique database IDs */
+
+#include <string.h>
+
+#define MAX_DBID_LEN 48
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+	typedef char dbid_t[MAX_DBID_LEN];
+
+	/** generates ID for data in shared memory at address given by data_ptr */
+	void generate_dbid_ptr(dbid_t dst, void *data_ptr);
+
+#ifdef SER
+	void generate_dbid(dbid_t dst);
+#endif
+
+/* macros for conversion to string representation of DBID
+ * (if dbid becomes structure with binary information
+ * these should be removed and replaced by functions) */
+#define dbid_strlen(id) strlen(id)
+#define dbid_strptr(id) ((char *)(id))
+
+#define dbid_clear(id) \
+	do {               \
+		(id)[0] = 0;   \
+	} while(0)
+
+#define is_dbid_empty(id) (!(id)[0])
+
+/** Copies dbid as string into destination. The destination string
+ * data buffer MUST be allocated in needed size! */
+#define dbid_strcpy(dst, id, l)  \
+	do {                         \
+		memcpy((dst)->s, id, l); \
+		(dst)->len = l;          \
+	} while(0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 4 - 0
src/lib/cds/doc/Makefile

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

+ 53 - 0
src/lib/cds/doc/cds.xml

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE book PUBLIC '-//OASIS//DTD DocBook XML V4.2//EN'
+'http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd'[
+	<!ENTITY % local.common.attrib "xml:base  CDATA  #IMPLIED">
+]>
+
+<book lang="en">
+<bookinfo>
+	<title>Common Data Structures (libcds)</title>
+	<author><firstname>Václav</firstname><surname>Kubart</surname></author>
+	<abstract><para>Description of CDS (Common Data Structures) library.
+	</para></abstract>
+</bookinfo>
+
+<preface><title>Preface</title>
+<para>This library contains many useful functions and data structures. It is
+possible to use it with Sip Express Router (SER) or without it. In the first case it
+is able to use some internal SER's data types like strings.
+</para>
+
+<section><title>Conventions</title>
+<para>There is list of conventions used in this library:
+<itemizedlist>
+	<listitem><para>data types (structures, enums, ...) have their names with suffix 
+	<quote>_t</quote> (<structname>dstring_t</structname>, 
+	<structname>str_t</structname>, ...)</para></listitem>
+	<listitem><para>many functions have prefix according to data structure on
+	which are operating (like <function>dstr_append</function> which operates on
+	<structname>dstring_t</structname> data structure)</para></listitem>
+	<listitem><para>most functions return 0 as successful result and nonzero
+	value as error</para></listitem>
+</itemizedlist>
+</para>
+</section>
+
+<section id="libcds.dependencies"><title>Dependencies</title>
+<para>This library depends only on standard C libraries and needs no other
+external libraries.</para>
+</section>
+
+</preface>
+
+<part><title>Reference</title>
+<include xmlns="http://www.w3.org/2001/XInclude" href="memory.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="sstr.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="dstring.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="serialization.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="sync.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="msg_queue.xml"/>
+</part>
+
+</book>

+ 50 - 0
src/lib/cds/doc/cds_free.xml

@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="cds_free"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>cds_free</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>cds_free</refname> <!-- function name -->
+<refpurpose>free allocated memory</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/memory.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>void <function>cds_free</function></funcdef>
+  <paramdef>void *<parameter>ptr</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Frees memory allocated using <function>cds_malloc</function>.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns 0 on success, non-zero on error.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 46 - 0
src/lib/cds/doc/cds_free_ptr.xml

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="cds_free_ptr"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>cds_free_ptr</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>cds_free_ptr</refname> <!-- function name -->
+<refpurpose>pointer to cds_free function independent on cds_free
+implementation (macro, ...)</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/memory.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>void <function>cds_free_ptr</function></funcdef>
+  <paramdef>void *<parameter>ptr</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Pointer to memory deallocation function. It is independent on
+<function>cds_free</function> implementation.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="cds_free"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 52 - 0
src/lib/cds/doc/cds_malloc.xml

@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="cds_malloc"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>cds_malloc</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>cds_malloc</refname> <!-- function name -->
+<refpurpose>memory allocation</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/memory.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>void *<function>cds_malloc</function></funcdef>
+  <paramdef>unsigned int <parameter>size</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Allocates Memory of given size. If compiled with SER it internally uses
+<function>shm_malloc</function>, if compiled without SER it uses 
+<function>malloc</function>.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>Returns NULL on error, pointer to allocated memory otherwise.
+<!-- return value description -->
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="cds_malloc"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 46 - 0
src/lib/cds/doc/cds_malloc_ptr.xml

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="cds_malloc_ptr"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>cds_malloc_ptr</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>cds_malloc_ptr</refname> <!-- function name -->
+<refpurpose>pointer to cds_malloc function independent on cds_malloc
+implementation (macro, ...)</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/memory.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>void *<function>cds_malloc_ptr</function></funcdef>
+  <paramdef>unsigned int <parameter>size</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Pointer to memory allocation function. It is independent on
+<function>cds_malloc</function> implementation.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="cds_malloc"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 46 - 0
src/lib/cds/doc/cds_mutex_destroy.xml

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="cds_mutex_destroy"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>cds_mutex_destroy</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>cds_mutex_destroy</refname> <!-- function name -->
+<refpurpose>mutex destruction</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/sync.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>cds_mutex_destroy</function></funcdef>
+  <paramdef>cds_mutex_t *<parameter>m</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Destroys mutex. It is defined as macro now thus type control and return
+value specification may be problematic!
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<!-- references to other pages -->
+<xref linkend="cds_mutex_t"/>, <xref linkend="cds_mutex_init"/>,
+<xref linkend="cds_mutex_lock"/>, <xref linkend="cds_mutex_unlock"/>
+</para>
+</refsect1>
+
+</refentry> 
+

+ 45 - 0
src/lib/cds/doc/cds_mutex_init.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="cds_mutex_init"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>cds_mutex_init</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>cds_mutex_init</refname> <!-- function name -->
+<refpurpose>mutex initialization</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/sync.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>cds_mutex_init</function></funcdef>
+  <paramdef>cds_mutex_t *<parameter>m</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Initializes mutex. It is defined as macro now thus type control and return
+value specification may be problematic!
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>See Also</title>
+<!-- references to other pages -->
+<para><xref linkend="cds_mutex_t"/>, <xref linkend="cds_mutex_destroy"/>,
+<xref linkend="cds_mutex_lock"/>, <xref linkend="cds_mutex_unlock"/>
+</para>
+</refsect1>
+
+</refentry> 
+

+ 46 - 0
src/lib/cds/doc/cds_mutex_lock.xml

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="cds_mutex_lock"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>cds_mutex_lock</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>cds_mutex_lock</refname> <!-- function name -->
+<refpurpose>mutex lock</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/sync.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>cds_mutex_lock</function></funcdef>
+  <paramdef>cds_mutex_t *<parameter>m</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Locks mutex. It is defined as macro now thus type control and return
+value specification may be problematic!
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<!-- references to other pages -->
+<xref linkend="cds_mutex_t"/>, <xref linkend="cds_mutex_init"/>,
+<xref linkend="cds_mutex_destroy"/>, <xref linkend="cds_mutex_unlock"/>
+</para>
+</refsect1>
+
+</refentry> 
+

+ 41 - 0
src/lib/cds/doc/cds_mutex_t.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="cds_mutex_t">
+
+<refmeta><refentrytitle>cds_mutex_t</refentrytitle>
+<manvolnum>3</manvolnum></refmeta>
+
+<refnamediv><refname>cds_mutex_t</refname>
+<refpurpose>wrapper type for mutex</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv><synopsis>
+#include &lt;cds/sync.h&gt;
+
+outside of SIP Express Router:
+
+#include &lt;pthread.h&gt;
+#define cds_mutex_t   pthread_mutex_t
+
+inside of SIP Express Router:
+
+#define cds_mutex_t   gen_lock_t
+
+</synopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Wrapper type for mutex. It is defined as macro now, but this may change.
+</para> 
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para><xref linkend="cds_mutex_init"/>, <xref linkend="cds_mutex_destroy"/>,
+<xref linkend="cds_mutex_lock"/>, <xref linkend="cds_mutex_unlock"/>
+</para>
+</refsect1>
+
+</refentry> 
+

+ 46 - 0
src/lib/cds/doc/cds_mutex_unlock.xml

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="cds_mutex_unlock"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>cds_mutex_unlock</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>cds_mutex_unlock</refname> <!-- function name -->
+<refpurpose>mutex unlock</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/sync.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>cds_mutex_unlock</function></funcdef>
+  <paramdef>cds_mutex_t *<parameter>m</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Unlocks mutex. It is defined as macro now thus type control and return
+value specification may be problematic!
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<!-- references to other pages -->
+<xref linkend="cds_mutex_t"/>, <xref linkend="cds_mutex_init"/>,
+<xref linkend="cds_mutex_destroy"/>, <xref linkend="cds_mutex_lock"/>
+</para>
+</refsect1>
+
+</refentry> 
+

+ 64 - 0
src/lib/cds/doc/create_message.xml

@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="create_message"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>create_message</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>create_message</refname> <!-- function name -->
+<refpurpose>allocates and initializes message</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/msg_queue.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>create_message</function></funcdef>
+  <paramdef>void *<parameter>data</parameter></paramdef>
+  <paramdef>int <parameter>data_len</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+
+<para>Allocates message using <function>cds_malloc</function> and initializes
+its content so it will be freed automatically. Pointer to the explicitly
+allocated data is set to <parameter>data</parameter> and its length is set to
+<parameter>data_len</parameter>. Message created by <function>create_message</function> 
+should be freed using <function>message_free</function>.</para>
+
+<para>Unremoved messages created this way are freed automatically in
+<function>msg_queue_destroy</function> using <function>free_message</function>.
+</para>
+
+<para>Calling <function>free_message</function> to such message frees the
+message and the data given by parameter <parameter>data</parameter> too, thus
+they can NOT be freed by the caller!
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns NULL on error, pointer to initialized message structure otherwise.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="create_message_ex"/>, <xref linkend="init_message_ex"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 63 - 0
src/lib/cds/doc/create_message_ex.xml

@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="create_message_ex"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>create_message_ex</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>create_message_ex</refname> <!-- function name -->
+<refpurpose>create and initialize message</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/msg_queue.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>mq_message_t *<function>create_message_ex</function></funcdef>
+  <paramdef>int <parameter>data_len</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+
+<para>Allocates message with data of given size
+(<parameter>data_len</parameter>) using <function>cds_malloc</function>. It
+initializes message content so it will be freed automatically. 
+Pointer to allocated data should be obtained by 
+<function>get_message_data</function>.
+</para>
+
+<para>Messages created by <function>create_message_ex</function> 
+should be freed using <function>message_free</function>.</para>
+
+<para>Unremoved messages created this way are freed automatically in
+<function>msg_queue_destroy</function> using <function>free_message</function>.
+</para>
+
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns NULL on error, pointer to initialized message structure otherwise.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="create_message"/>, <xref linkend="init_message_ex"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 49 - 0
src/lib/cds/doc/destroy_sstream.xml

@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="destroy_sstream"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>destroy_sstream</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>destroy_sstream</refname> <!-- function name -->
+<refpurpose>destroys input/output serialization stream</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/serialize.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>void <function>destroy_sstream</function></funcdef>
+  <paramdef>sstream_t *<parameter>ss</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>
+Destroys serialization stream and frees all internal data buffers. After calling
+this function no other serialization stream manipulation
+function except <function>init_input_sstream</function> or
+<function>init_output_stream</function> can be called.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="sstream_t"/>, <xref linkend="init_input_sstream"/>, <xref
+linkend="init_output_sstream"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 77 - 0
src/lib/cds/doc/dstr_append.xml

@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="dstr_append">
+
+<refmeta><refentrytitle>dstr_append</refentrytitle>
+<manvolnum>3</manvolnum></refmeta>
+
+<refnamediv>
+<refname>dstr_append</refname>
+<refname id="dstr_append_str">dstr_append_str</refname>
+<refname id="dstr_append_zt">dstr_append_zt</refname>
+<refpurpose>append string to <structname>dstring_t</structname>
+structure</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+
+<funcsynopsisinfo>
+#include &lt;cds/dstring.h&gt;
+</funcsynopsisinfo>
+
+<funcprototype>
+  <funcdef>int <function>dstr_append</function></funcdef>
+  <paramdef>dstring_t *<parameter>dstr</parameter></paramdef>
+  <paramdef>const char *<parameter>s</parameter></paramdef>
+  <paramdef>int <parameter>len</parameter></paramdef>
+</funcprototype>
+
+<funcprototype>
+  <funcdef>int <function>dstr_append_str</function></funcdef>
+  <paramdef>dstring_t *<parameter>dstr</parameter></paramdef>
+  <paramdef>const str_t *<parameter>s</parameter></paramdef>
+</funcprototype>
+
+<funcprototype>
+  <funcdef>int <function>dstr_append_zt</function></funcdef>
+  <paramdef>dstring_t *<parameter>dstr</parameter></paramdef>
+  <paramdef>const char *<parameter>s</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>All these functions are used for appending strings to dynamic string. They
+differ only in the string and its length specification.
+<variablelist>
+<varlistentry>
+	<term><function>dstr_append</function></term>
+	<listitem><para>appends data from buffer <parameter>s</parameter> of
+	length <parameter>len</parameter></para></listitem>
+</varlistentry>
+<varlistentry>
+	<term><function>dstr_append_str</function></term>
+	<listitem><para>appends content of string <parameter>s</parameter>
+	(see <xref linkend="str_t"/>)</para></listitem>
+</varlistentry>
+<varlistentry>
+	<term><function>dstr_append_zt</function></term>
+	<listitem><para>appends content of zero terminated string <parameter>s</parameter></para></listitem>
+</varlistentry>
+</variablelist>
+</para>
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>All these functions return 0 if successful, nonzero otherwise.</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para><xref linkend="dstring_t"/></para>
+</refsect1>
+
+</refentry> 
+

+ 74 - 0
src/lib/cds/doc/dstr_get_data.xml

@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="dstr_get_data">
+
+<refmeta><refentrytitle>dstr_get_data</refentrytitle>
+<manvolnum>3</manvolnum></refmeta>
+
+<refnamediv>
+<refname>dstr_get_data</refname>
+<refname id="dstr_get_data_length">dstr_get_data_length</refname>
+<refname id="dstr_get_data_str">dstr_get_data_str</refname>
+<refpurpose>exporting data from <structname>dstring_t</structname>
+structure</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+
+<funcsynopsisinfo>
+#include &lt;cds/dstring.h&gt;
+</funcsynopsisinfo>
+
+<funcprototype>
+  <funcdef>int <function>dstr_get_data_length</function></funcdef>
+  <paramdef>dstring_t *<parameter>dstr</parameter></paramdef>
+</funcprototype>
+
+<funcprototype>
+  <funcdef>int <function>dstr_get_data</function></funcdef>
+  <paramdef>dstring_t *<parameter>dstr</parameter></paramdef>
+  <paramdef>char *<parameter>dst</parameter></paramdef>
+</funcprototype>
+
+<funcprototype>
+  <funcdef>int <function>dstr_get_data_str</function></funcdef>
+  <paramdef>dstring_t *<parameter>dstr</parameter></paramdef>
+  <paramdef>str_t *<parameter>dst</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para><function>dstr_get_data_length</function> function is used to determine
+the size of data present in dynamic string. It returns negative value on error.</para>
+
+<para><function>dstr_get_data</function> copies data from internal buffers into
+given character array allocated by caller. The data size can be 
+determined by <function>dstr_get_data_length</function> call.
+</para>
+
+<para><function>dstr_get_data_str</function> copies data from internal buffers into
+internally allocated string. This string is returned in the <varname>dst</varname>
+parameter.
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>Functions <function>dstr_get_data</function> and
+<function>dstr_get_data_str</function> return 0 if successful, nonzero otherwise.
+</para>
+<para>Function <function>dstr_get_data_length</function> returns negative value
+on error, zero if there is no data in dynamic string and positive if there was
+no error and data present.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para><xref linkend="dstring_t"/></para>
+</refsect1>
+
+</refentry> 

+ 55 - 0
src/lib/cds/doc/dstr_init.xml

@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="dstr_init">
+
+<refmeta><refentrytitle>dstr_init</refentrytitle>
+<manvolnum>3</manvolnum></refmeta>
+
+<refnamediv>
+<refname>dstr_init</refname>
+<refname>dstr_destroy</refname>
+<refpurpose>initialization and destruction of <structname>dstring_t</structname>
+structure</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+
+<funcsynopsisinfo>
+#include &lt;cds/dstring.h&gt;
+</funcsynopsisinfo>
+
+<funcprototype>
+  <funcdef>int <function>dstr_init</function></funcdef>
+  <paramdef>dstring_t *<parameter>dstr</parameter></paramdef>
+  <paramdef>int <parameter>buff_size</parameter></paramdef>
+</funcprototype>
+
+<funcprototype>
+  <funcdef>int <function>dstr_destroy</function></funcdef>
+  <paramdef>dstring_t *<parameter>dstr</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para><function>dstr_init</function> function initializes
+<structname>dstring_t</structname> structure. The
+value of <varname>buff_size</varname> is the size of newly allocated data
+buffers. These buffers are internal and are allocated if needed by any of
+dstring functions.</para>
+
+<para><function>dstr_destroy</function> function destroys all allocated data
+buffers. After calling <function>dstr_destroy</function> can't be called any of
+dstring manipulation functions except <function>dstr_init</function>.
+</para>
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>Both functions return 0 if successful, nonzero otherwise.
+</para>
+</refsect1>
+
+</refentry> 

+ 21 - 0
src/lib/cds/doc/dstring.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<reference><title>Dynamic string</title>
+
+<partintro>
+<para>Dynamic string is data structure used for simple string operations
+hiding internal operations like memory allocations from the user.</para>
+
+<para>Functions and data structures for dynamic string are declared in 
+<filename class='headerfile'>dstring.h</filename>.</para>
+</partintro>
+
+<include xmlns="http://www.w3.org/2001/XInclude" href="dstring_t.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="dstr_init.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="dstr_append.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="dstr_get_data.xml"/>
+
+</reference>

+ 103 - 0
src/lib/cds/doc/dstring_t.xml

@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="dstring_t">
+
+<refmeta><refentrytitle>dstring_t</refentrytitle>
+<manvolnum>3</manvolnum></refmeta>
+
+<refnamediv><refname>dstring_t</refname>
+<refpurpose>data structure for dynamic string representation</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv><synopsis>
+#include &lt;cds/dstring.h&gt;
+
+typedef struct _dstring_t {
+	dlink_t buffers;
+	int len;
+	int buff_size;
+} dstring_t;
+</synopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>This structure represents dynamic string. It allows concatenation of
+multiple strings without worry about memory allocations.</para>
+
+<para>Internally it uses list of data buffers which are allocated 
+if needed. The content of dynamic string may be copied out from internal buffers
+using simple function call (see <xref linkend="dstr_get_data"/>). Internal
+buffers are allocated in package memory (when compiled with SER)!
+</para>
+
+<para>This structure is used as base for simple object serialization (see <xref
+linkend="serialization"/>).
+</para>
+
+<refsect2><title>Members</title>
+<para><variablelist>
+<varlistentry>
+	<term><varname>buffers</varname></term>
+	<listitem><para>linked list of allocated data buffers</para></listitem>
+</varlistentry>
+<varlistentry>
+	<term><varname>len</varname></term>
+	<listitem><para>whole string length</para></listitem>
+</varlistentry>
+<varlistentry>
+	<term><varname>buff_size</varname></term>
+	<listitem><para>size of newly allocated buffers</para></listitem>
+</varlistentry>
+</variablelist></para>
+<para>Warning - structure internals may change! For manipulation use
+manipulation functions.</para>
+</refsect2>
+
+</refsect1>
+
+<refsect1><title>Example</title>
+<programlisting>
+#include &lt;cds/dstring.h&gt;
+#include &lt;cds/sstr.h&gt;
+
+int main(int argc, char **argv)
+{
+	dstring_t str;
+	str_t s;
+
+	dstr_init(&amp;str, 256);
+	dstr_append_zt(&amp;str,"This is a ");
+	dstr_append_zt(&amp;str,"very long ");
+	dstr_append_zt(&amp;str,"string.");
+	if (dstr_get_str(&amp;str, &amp;s) == 0) {
+		printf("result: %.*s\n", FMT_STR(s));	
+		str_free_content(&amp;s);
+	}
+	dstr_destroy(&amp;str);
+
+	return 0;
+}	
+</programlisting>
+<para>This will result in</para>
+<para><computeroutput>result: This is a very long
+string.</computeroutput>
+</para>
+</refsect1>
+
+<refsect1><title>Todo</title>
+<para>Create a function like sprintf.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="dstr_init"/>,
+<xref linkend="dstr_get_data"/>,
+<xref linkend="dstr_append"/>,
+<xref linkend="str_t"/>
+</para>
+</refsect1>
+
+</refentry> 

+ 51 - 0
src/lib/cds/doc/free_message.xml

@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="free_message"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>free_message</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>free_message</refname> <!-- function name -->
+<refpurpose>free message</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/msg_queue.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>void <function>free_message</function></funcdef>
+  <paramdef>mq_message_t *<parameter>msg</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Frees message. If data is allocated explicitly it frees it using
+<function>cds_free</function>,
+if they are allocated implicitly, it is freed together with message. Thus simple
+data structures are deallocated automatically in both cases. There might be a
+problem with more complicated structures with internal pointers to other
+structures - for these you can set destroy function using
+<function>set_data_destroy_function</function>.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="create_message"/>, <xref linkend="create_message_ex"/>, <xref
+linkend="init_message_ex"/>, <xref linkend="set_data_destroy_function"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 55 - 0
src/lib/cds/doc/get_serialized_sstream.xml

@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="get_serialized_sstream"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>get_serialized_sstream</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>get_serialized_sstream</refname> <!-- function name -->
+<refpurpose>get output stream data</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/serialize.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>get_serialized_sstream</function></funcdef>
+  <paramdef>sstream_t *<parameter>ss</parameter></paramdef>
+  <paramdef>str_t *<parameter>dst</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>
+Copies data stored during output serialization into given destination. It allocates buffer
+necessary for serialized data using cds_malloc function. These data can be freed
+using <function>str_free_content</function>.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns 0 on success, non-zero on error.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="sstream_t"/>, <xref linkend="str_free_content"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 56 - 0
src/lib/cds/doc/init_input_sstream.xml

@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="init_input_sstream"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>init_input_sstream</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>init_input_sstream</refname> <!-- function name -->
+<refpurpose>initializes input serialization stream</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis> <!-- usage -->
+
+<funcsynopsisinfo>
+#include &lt;cds/serialize.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>init_input_sstream</function></funcdef>
+  <paramdef>sstream_t *<parameter>ss</parameter></paramdef>
+  <paramdef>char *<parameter>data_in</parameter></paramdef>
+  <paramdef>int <parameter>data_len</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Initializes serialization stream as input. Input data are read from char
+array given by pointer <parameter>data_in</parameter> and length
+<parameter>data_len</parameter>.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+Returns 0 if successful, nonzero otherwise.
+<!-- return value description -->
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="sstream_t"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 55 - 0
src/lib/cds/doc/init_message_ex.xml

@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="init_message_ex"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>init_message_ex</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>init_message_ex</refname> <!-- function name -->
+<refpurpose>initialize message</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/msg_queue.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>void <function>init_message_ex</function></funcdef>
+  <paramdef>mq_message_t *<parameter>m</parameter></paramdef>
+  <paramdef>void *<parameter>data</parameter></paramdef>
+  <paramdef>int <parameter>data_len</parameter></paramdef>
+  <paramdef>destroy_function_f <parameter>func</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Initializes message structure with given data and given data length like
+<function>create_message</function> but without its allocation. </para>
+<para>
+Parameter <parameter>func</parameter> specifies function called on data pointer
+before freeing the message in <function>free_message</function>. It can be NULL.
+This function may be used for example for memory deallocation (for example may
+have value of <function>cds_free_ptr</function>) or some more complicated
+function for freeing complex data structure with pointers inside or so.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<!-- references to other pages -->
+<xref linkend="create_message"/>, <xref linkend="create_message_ex"/>, <xref
+linkend="free_message"/>
+</para>
+</refsect1>
+
+</refentry> 
+

+ 55 - 0
src/lib/cds/doc/init_output_sstream.xml

@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="init_output_sstream"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>init_output_sstream</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>init_output_sstream</refname> <!-- function name -->
+<refpurpose>initializes serialization stream for output</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/serialize.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>init_output_sstream</function></funcdef>
+  <paramdef>sstream_t *<parameter>ss</parameter></paramdef>
+  <paramdef>int <parameter>out_buff_resize</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Initializes given serialization stream for output. Parameter
+<parameter>out_buff_resize</parameter> is stored into
+<structname>sstream_t</structname> structure and specifies the size of newly
+allocated data buffers. Data buffers are allocated when needed during output.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+Returns 0 on success, non-zero on error.
+<!-- return value description -->
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<!-- references to other pages -->
+<xref linkend="sstream_t"/>, <xref linkend="dstring_t"/>
+</para>
+</refsect1>
+
+</refentry> 
+

+ 50 - 0
src/lib/cds/doc/is_msg_queue_empty.xml

@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="is_msg_queue_empty"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>is_msg_queue_empty</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>is_msg_queue_empty</refname> <!-- function name -->
+<refpurpose>test if message queue empty</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/msg_queue.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>is_msg_queue_empty</function></funcdef>
+  <paramdef>msg_queue_t *<parameter>q</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Tests message queue if it is empty.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>Returns nonzero if message queue empty, zero otherwise.
+<!-- return value description -->
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="push_message"/>, <xref linkend="pop_message"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 39 - 0
src/lib/cds/doc/memory.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<reference id="memory">
+<title>Memory operations</title>
+
+<partintro>
+<para>Memory operations are common for whole CDS library. Because it must work
+together with SER's memory management and must work without it too, there are
+wrapper macros for memory allocation/deallocation.</para>
+
+<para>These macros were functions and it may change in the future, but macros
+are probably better - they allow better debugging than functions. There are
+defined another macros (see <xref linkend="cds_malloc_ptr"/>, <xref
+linkend="cds_free_ptr"/>), which point and will point to allocation/deallocation
+functions, thus they may be used as function pointers.
+<!--
+standalone functions (?macros in the future?) which cover internal
+implementation of memory allocation/deallocation functions.-->
+</para>
+
+<para>It is possible to redefine these macros/functions to help with memory debugging
+or for monitoring purposes or so.
+</para>
+
+<!--
+<para>It might be useful some parts of code determined for SER probe out of it,
+with a memory debugging tool like valgrind
+</para> -->
+</partintro>
+
+<include xmlns="http://www.w3.org/2001/XInclude" href="cds_malloc.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="cds_free.xml"/>
+
+<include xmlns="http://www.w3.org/2001/XInclude" href="cds_malloc_ptr.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="cds_free_ptr.xml"/>
+</reference>

+ 72 - 0
src/lib/cds/doc/mq_message_t.xml

@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="mq_message_t">
+
+<refmeta><refentrytitle>mq_message_t</refentrytitle>
+<manvolnum>3</manvolnum></refmeta>
+
+<refnamediv><refname>mq_message_t</refname>
+<refpurpose>message data structure</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv><synopsis>
+#include &lt;cds/msg_queue.h&gt;
+
+typedef struct _mq_message_t {
+	void *data;
+	int data_len;
+	struct _mq_message_t *next;
+	destroy_function_f destroy_function;
+	enum { 
+		message_allocated_with_data, 
+		message_holding_data_ptr 
+	} allocation_style;
+	char data_buf[1];
+} mq_message_t;
+</synopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+
+<para>Data structure used as basic element in message queue. Pointer to
+message data should be obtained by <function>get_message_data</function>.
+</para>
+
+<para>There are more possibilities how to allocate message data:
+<itemizedlist>
+	<listitem><para>explicitly, data buffer is allocated outside of
+	<structname>mq_message_t</structname> structure and only pointer to it is stored
+	in this structure, see <xref linkend="create_message"/>
+	<!-- - in this case the data must be deallocated explicitly--></para></listitem>
+	
+	<listitem><para>implicitly, data buffer is allocated together with
+	<structname>mq_message_t</structname> structure - data must be copied into
+	it after structure allocation, see <xref linkend="create_message_ex"/></para></listitem>
+
+	<listitem><para>there is third possibility, that data and message - both -
+	are allocated by caller without using
+	<function>create_message</function>, <function>create_message_ex</function> and 
+	<function>msg_free</function>, see <xref linkend="init_message_ex"/></para>
+	</listitem>
+</itemizedlist>
+</para>
+
+<para>More different data allocation methods are due to more efficiency - less
+memory allocation calls and less fragmentation in second case, but more common
+and may be simpler for usage in first case.
+</para>
+
+<para>Warning: internal implementation of this structure may change, use it only
+through existing functions.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para><xref linkend="msg_queue_t"/>
+</para>
+</refsect1>
+
+</refentry> 
+

+ 36 - 0
src/lib/cds/doc/msg_queue.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<reference id="msg_queue">
+<title>Message queue</title>
+
+<partintro>
+<para>Message queue is implementation of simple FIFO. It is declared in
+<filename>msg_queue.h</filename>.
+</para>
+
+<!--
+<para> TODO: describe element allocation methods !
+</para> -->
+</partintro>
+
+<include xmlns="http://www.w3.org/2001/XInclude" href="msg_queue_t.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="mq_message_t.xml"/>
+
+<include xmlns="http://www.w3.org/2001/XInclude" href="msg_queue_init.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="msg_queue_init_ex.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="msg_queue_destroy.xml"/>
+
+<include xmlns="http://www.w3.org/2001/XInclude" href="push_message.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="pop_message.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="is_msg_queue_empty.xml"/>
+
+<include xmlns="http://www.w3.org/2001/XInclude" href="create_message.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="create_message_ex.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="init_message_ex.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="set_data_destroy_function.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="free_message.xml"/>
+
+</reference>

+ 54 - 0
src/lib/cds/doc/msg_queue_destroy.xml

@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="msg_queue_destroy"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>msg_queue_destroy</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>msg_queue_destroy</refname> <!-- function name -->
+<refpurpose>destroy message queue</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/msg_queue.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>void <function>msg_queue_destroy</function></funcdef>
+  <paramdef>msg_queue_t *<parameter>q</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Destroys initialized message queue. After calling
+<function>msg_queue_destroy</function> can not be called any of message queue
+manipulation functions except <function>msg_queue_init</function>.
+<!-- detailed description -->
+</para>
+
+<para>All messages which stay in the queue  
+are automatically freed using <function>free_message</function>. 
+</para>
+
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="msg_queue_init"/>, <xref linkend="msg_queue_init_ex"/>, <xref
+linkend="msg_queue_t"/>, <xref linkend="mq_message_t"/>, <xref
+linkend="free_message"/>, <xref linkend="init_message_ex"/>
+<!--, <xref
+linkend="free_message"/>-->
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 51 - 0
src/lib/cds/doc/msg_queue_init.xml

@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="msg_queue_init"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>msg_queue_init</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>msg_queue_init</refname> <!-- function name -->
+<refpurpose>message queue initialization</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/msg_queue.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>msg_queue_init</function></funcdef>
+  <paramdef>msg_queue_t *<parameter>q</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Initializes synchronized (using internal mutex) message queue structure.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns 0 on success, non-zero on error.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="msg_queue_init_ex"/>, <xref linkend="msg_queue_destroy"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 55 - 0
src/lib/cds/doc/msg_queue_init_ex.xml

@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="msg_queue_init_ex"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>msg_queue_init_ex</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>msg_queue_init_ex</refname> <!-- function name -->
+<refpurpose>message queue initialization</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/msg_queue.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>msg_queue_init_ex</function></funcdef>
+  <paramdef>msg_queue_t *<parameter>q</parameter></paramdef>
+  <paramdef>int <parameter>synchronized</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Initializes message queue structure. The value of
+<parameter>synchronized</parameter> may be 0 or 1. Zero means, that the message
+queue will not use mutex for internal data access (will be NOT synchronized), 1
+means that message queue will be synchronized by mutex created internally.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns 0 on success, non-zero on error.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="msg_queue_init"/>, <xref linkend="msg_queue_destroy"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 43 - 0
src/lib/cds/doc/msg_queue_t.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="msg_queue_t">
+
+<refmeta><refentrytitle>msg_queue_t</refentrytitle>
+<manvolnum>3</manvolnum></refmeta>
+
+<refnamediv><refname>msg_queue_t</refname>
+<refpurpose>message queue data structure</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv><synopsis>
+#include &lt;cds/msg_queue.h&gt;
+
+typedef struct msg_queue {
+	mq_message_t *first;
+	mq_message_t *last;
+	cds_mutex_t q_mutex;
+	int use_mutex;
+} msg_queue_t;
+
+</synopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Message queue is implemented as simple linked list of elements. Message
+queue may be locked or not - it depends on initialization.
+</para> 
+<para>Warning: internal implementation of this structure may change, use it only
+through existing functions.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="mq_message_t"/>
+</para>
+</refsect1>
+
+</refentry> 
+

+ 53 - 0
src/lib/cds/doc/pop_message.xml

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="pop_message"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>pop_message</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>pop_message</refname> <!-- function name -->
+<refpurpose>pop message from the queue</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/msg_queue.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>mq_message_t *<function>pop_message</function></funcdef>
+  <paramdef>msg_queue_t *<parameter>q</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Removes first message from the queue. If the queue is empty or an error
+occurred it returns NULL value. Removed messages are NOT automatically freed -
+caller must use <function>free_message</function> or free it itself (see <xref
+linkend="free_message"/>)!
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>Returns pointer to message removed from the queue. If the queue is empty
+or an error occurred the return value is NULL.
+<!-- return value description -->
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="push_message"/>, <xref linkend="free_message"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 60 - 0
src/lib/cds/doc/push_message.xml

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="push_message"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>push_message</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>push_message</refname> <!-- function name -->
+<refpurpose>push message into message queue</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/msg_queue.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>push_message</function></funcdef>
+  <paramdef>msg_queue_t *<parameter>q</parameter></paramdef>
+  <paramdef>mq_message_t *<parameter>msg</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Function pushes initialized message into message queue. This
+message may be removed from the queue using <function>pop_message</function>.
+Unremoved messages are automatically freed by <function>msg_queue_destroy</function> 
+(depending on message initialization, see <xref
+linkend="create_message"/>, <xref linkend="create_message_ex"/> and <xref
+linkend="init_message_ex"/>).
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns 0 on success, non-zero on error.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<!-- references to other pages -->
+<xref linkend="pop_message"/>, 
+<xref linkend="create_message"/>, 
+<xref linkend="create_message_ex"/>, 
+<xref linkend="init_message_ex"/>
+</para>
+</refsect1>
+
+</refentry> 
+

+ 36 - 0
src/lib/cds/doc/serialization.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<reference id="serialization">
+<title>Serialization</title>
+
+<partintro>
+<para>Serialization is a simple way to store and load data structures. It is
+used for example for storing SIP dialogs into database in SER's PA module.</para>
+<para>There is a set of functions for serializing basic data elements (strings,
+numbers, ...). These functions can be used as base for complex structures
+serialization (see <xref linkend="sstream_t.example"/>).</para>
+</partintro>
+
+<include xmlns="http://www.w3.org/2001/XInclude" href="sstream_t.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="init_input_sstream.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="init_output_sstream.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="get_serialized_sstream.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="destroy_sstream.xml"/>
+
+<include xmlns="http://www.w3.org/2001/XInclude" href="sstream_put.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="sstream_put_str.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="sstream_put_zt.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="sstream_get.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="sstream_get_str.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="sstream_get_str_ex.xml"/>
+
+<include xmlns="http://www.w3.org/2001/XInclude" href="serialize_int.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="serialize_uint.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="serialize_char.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="serialize_uchar.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="serialize_str.xml"/>
+
+</reference>

+ 59 - 0
src/lib/cds/doc/serialize_char.xml

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="serialize_char"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>serialize_char</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>serialize_char</refname> <!-- function name -->
+<refpurpose>character serialization</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/serialize.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>serialize_char</function></funcdef>
+  <paramdef>sstream_t *<parameter>ss</parameter></paramdef>
+  <paramdef>char *<parameter>c</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Serializes character. This means that in the case of input stream this
+functions sets value of given character parameter to value read from stream, 
+in the case of output stream it
+writes the character given in parameter into that stream.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns 0 on success, non-zero on error.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="sstream_t"/>, 
+<xref linkend="serialize_int"/>, 
+<xref linkend="serialize_uint"/>, 
+<xref linkend="serialize_uchar"/>, 
+<xref linkend="serialize_str"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 59 - 0
src/lib/cds/doc/serialize_int.xml

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="serialize_int"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>serialize_int</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>serialize_int</refname> <!-- function name -->
+<refpurpose>integer serialization</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/serialize.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>serialize_int</function></funcdef>
+  <paramdef>sstream_t *<parameter>ss</parameter></paramdef>
+  <paramdef>int *<parameter>num</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Serializes number. This means that in case of input stream this
+functions sets value of given integer parameter to value read from stream, 
+in case of output stream it
+writes the number given in parameter into that stream.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns 0 on success, non-zero on error.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="sstream_t"/>
+<xref linkend="serialize_uint"/>, 
+<xref linkend="serialize_char"/>, 
+<xref linkend="serialize_uchar"/>, 
+<xref linkend="serialize_str"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 59 - 0
src/lib/cds/doc/serialize_str.xml

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="serialize_str"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>serialize_str</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>serialize_str</refname> <!-- function name -->
+<refpurpose>string serialization</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/serialize.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>serialize_str</function></funcdef>
+  <paramdef>sstream_t *<parameter>ss</parameter></paramdef>
+  <paramdef>str_t *<parameter>s</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Serializes string. This means that in the case of input stream this
+functions reads string from the stream (allocated using cds_malloc),
+in the case of output stream it
+writes the given string into that stream.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns 0 on success, non-zero on error.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="sstream_t"/>, 
+<xref linkend="serialize_int"/>, 
+<xref linkend="serialize_uint"/>, 
+<xref linkend="serialize_char"/>, 
+<xref linkend="serialize_uchar"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 59 - 0
src/lib/cds/doc/serialize_uchar.xml

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="serialize_uchar"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>serialize_uchar</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>serialize_uchar</refname> <!-- function name -->
+<refpurpose>unsigned character serialization</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/serialize.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>serialize_uchar</function></funcdef>
+  <paramdef>sstream_t *<parameter>ss</parameter></paramdef>
+  <paramdef>unsigned char *<parameter>c</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Serializes unsigned character. This means that in the case of input stream this
+functions sets value of given character parameter to value read from stream, 
+in the case of output stream it
+writes the character given in parameter into that stream.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns 0 on success, non-zero on error.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="sstream_t"/>, 
+<xref linkend="serialize_int"/>, 
+<xref linkend="serialize_uint"/>, 
+<xref linkend="serialize_char"/>, 
+<xref linkend="serialize_str"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 59 - 0
src/lib/cds/doc/serialize_uint.xml

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="serialize_uint"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>serialize_uint</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>serialize_uint</refname> <!-- function name -->
+<refpurpose>unsigned integer serialization</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/serialize.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>serialize_uint</function></funcdef>
+  <paramdef>sstream_t *<parameter>ss</parameter></paramdef>
+  <paramdef>unsigned int *<parameter>num</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Serializes number. This means that in the case of input stream this
+functions sets value of given unsigned integer parameter to value read from stream, 
+in the case of output stream it
+writes the number given in parameter into that stream.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns 0 on success, non-zero on error.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="sstream_t"/>, 
+<xref linkend="serialize_int"/>, 
+<xref linkend="serialize_char"/>, 
+<xref linkend="serialize_uchar"/>, 
+<xref linkend="serialize_str"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 71 - 0
src/lib/cds/doc/set_data_destroy_function.xml

@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="set_data_destroy_function"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>set_data_destroy_function</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>set_data_destroy_function</refname> <!-- function name -->
+<refpurpose>set function used to deallocate message data</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/msg_queue.h&gt; <!-- included headers -->
+
+typedef void (*destroy_function_f)(void *);
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>void <function>set_data_destroy_function</function></funcdef>
+  <paramdef>mq_message_t *<parameter>msg</parameter></paramdef>
+  <paramdef>destroy_function_f <parameter>func</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Set destroy function for message data. This function is called from
+<function>free_message</function> and is primarily used for deallocation of
+complex data structures or their content. It can be used on all types of
+messages (allocated using <function>create_message</function> or
+<function>create_message_ex</function> or initialized using
+<function>init_message_ex</function>).
+<!-- detailed description -->
+</para>
+
+<example><title>Usage with create_message_ex</title>
+<programlisting>
+str_t *s;
+mq_message_t *msg = create_message_ex(sizeof(str_t));
+set_data_destroy_function((destroy_function_f)str_free_content);
+s = (str_t*)get_message_data(msg);
+str_dup_zt(s, "something happened");
+</programlisting>
+</example>
+
+<example><title>Usage with create_message</title>
+<programlisting>
+str_t *s = cds_malloc(sizeof(str_t));
+mq_message_t *msg = create_message(s, sizeof(str_t));
+set_data_destroy_function((destroy_function_f)str_free);
+str_dup_zt(s, "something happened");
+</programlisting>
+</example>
+
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para><xref linkend="create_message"/>, <xref linkend="create_message_ex"/>,
+<xref linkend="init_message_ex"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 28 - 0
src/lib/cds/doc/sstr.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<reference id="sstr">
+<title>String</title>
+
+<partintro>
+<para>String is basic data structure. Standard zero terminated C strings have
+some bad properties which may slow down processing or disallow use of binary
+values. This structure is an attempt to do it better :-).</para>
+<para>This structure was taken from SIP Express
+Router due to it's usability and need of testing some parts of SER's code
+outside of <quote>SER's environment</quote>. Many of string functions were
+inspired by or directly taken from SER's code. Another reason for this structure 
+was to put string operations to one place and not leave them independently and
+often duplicately in SER's modules.</para>
+</partintro>
+
+<include xmlns="http://www.w3.org/2001/XInclude" href="str_t.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="str_dup.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="str_clear.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="str_free.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="str_free_content.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="str_other.xml"/>
+
+</reference>

+ 53 - 0
src/lib/cds/doc/sstream_get.xml

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="sstream_get"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>sstream_get</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>sstream_get</refname> <!-- function name -->
+<refpurpose>read data from input stream</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/serialize.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>sstream_get</function></funcdef>
+  <paramdef>sstream_t *<parameter>ss</parameter></paramdef>
+  <paramdef>char *<parameter>c</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Reads a character from input stream into <parameter>c</parameter>.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns 0 on success, non-zero on error.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="sstream_t"/>, <xref linkend="sstream_get_str"/>, <xref
+linkend="sstream_get_str_ex"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 58 - 0
src/lib/cds/doc/sstream_get_str.xml

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="sstream_get_str"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>sstream_get_str</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>sstream_get_str</refname> <!-- function name -->
+<refpurpose>read data from input stream</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/serialize.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>sstream_get_str</function></funcdef>
+  <paramdef>sstream_t *<parameter>ss</parameter></paramdef>
+  <paramdef>int <parameter>length</parameter></paramdef>
+  <paramdef>str_t *<parameter>dst</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Reads <parameter>len</parameter> bytes from input stream makes a copy of
+them and returns them in string <parameter>dst</parameter>. For allocation it
+uses cds_malloc function. The string may be freed using for example
+<function>str_free_content</function>. If there is not enough data to read (less
+than <parameter>len</parameter> bytes), the function returns error.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns 0 on success, non-zero on error. 
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="sstream_t"/>, <xref linkend="sstream_get"/>, <xref
+linkend="sstream_get_str_ex"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 57 - 0
src/lib/cds/doc/sstream_get_str_ex.xml

@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="sstream_get_str_ex"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>sstream_get_str_ex</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>sstream_get_str_ex</refname> <!-- function name -->
+<refpurpose>read data from input stream</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/serialize.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>sstream_get_str_ex</function></funcdef>
+  <paramdef>sstream_t *<parameter>ss</parameter></paramdef>
+  <paramdef>int <parameter>len</parameter></paramdef>
+  <paramdef>str_t *<parameter>dst</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Returns data buffer of requested length (<parameter>len</parameter>). If
+there is not enough data to read (less than <parameter>len</parameter> bytes), 
+the function returns error. The memory can NOT be freed because it is a part of
+input buffer!
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns 0 on success, non-zero on error. 
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="sstream_t"/>, <xref linkend="sstream_get"/>, <xref
+linkend="sstream_get_str"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 55 - 0
src/lib/cds/doc/sstream_put.xml

@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="sstream_put"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>sstream_put</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>sstream_put</refname> <!-- function name -->
+<refpurpose>store data into output stream</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/serialize.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>sstream_put</function></funcdef>
+  <paramdef>sstream_t *<parameter>ss</parameter></paramdef>
+  <paramdef>const char *<parameter>s</parameter></paramdef>
+  <paramdef>int <parameter>len</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Stores data into output stream. It copies data of size
+<parameter>len</parameter> from memory at address <parameter>s</parameter> into
+internal data buffers.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns 0 on success, non-zero on error.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="sstream_t"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 53 - 0
src/lib/cds/doc/sstream_put_str.xml

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="sstream_put_str"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>sstream_put_str</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>sstream_put_str</refname> <!-- function name -->
+<refpurpose>store data into output stream</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/serialize.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>sstream_put_str</function></funcdef>
+  <paramdef>sstream_t *<parameter>ss</parameter></paramdef>
+  <paramdef>const str_t *<parameter>s</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Stores data into output stream. It copies data from given string into
+internal data buffers.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns 0 on success, non-zero on error.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="sstream_t"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 53 - 0
src/lib/cds/doc/sstream_put_zt.xml

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="sstream_put_zt"> <!-- ID for references -->
+
+<refmeta>
+<refentrytitle>sstream_put_zt</refentrytitle> <!-- title shown in references -->
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
+
+<refnamediv>
+<refname>sstream_put_zt</refname> <!-- function name -->
+<refpurpose>store data into output stream</refpurpose> <!-- short function description -->
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;cds/serialize.h&gt; <!-- included headers -->
+</funcsynopsisinfo>
+
+<funcprototype> <!-- function prototype -->
+  <funcdef>int <function>sstream_put_zt</function></funcdef>
+  <paramdef>sstream_t *<parameter>ss</parameter></paramdef>
+  <paramdef>const char *<parameter>s</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Stores data into output stream. It copies data from zero-terminated string
+<parameter>s</parameter> into internal data buffers.
+<!-- detailed description -->
+</para>
+
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>
+<!-- return value description -->
+Returns 0 on success, non-zero on error.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="sstream_t"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 118 - 0
src/lib/cds/doc/sstream_t.xml

@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="sstream_t">
+
+<refmeta><refentrytitle>sstream_t</refentrytitle>
+<manvolnum>3</manvolnum></refmeta>
+
+<refnamediv><refname>sstream_t</refname>
+<refpurpose>input/output serialization stream</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv><synopsis>
+#include &lt;cds/serialize.h&gt;
+
+typedef struct {
+	dstring_t out;
+	str_t in;
+	int in_pos;
+	enum { sstream_in, sstream_out } type;
+} sstream_t;
+</synopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>This structure represents input and output serialization stream.</para> 
+<refsect2><title>Members</title>
+<para><variablelist>
+<varlistentry>
+	<term><varname>out</varname></term>
+	<listitem><para>Dynamic string holding output data in the case of output
+	stream.</para></listitem>
+</varlistentry>
+<varlistentry>
+	<term><varname>in</varname></term>
+	<listitem><para>String holding input data in the case of input 
+	stream.</para></listitem>
+</varlistentry>
+<varlistentry>
+	<term><varname>in_pos</varname></term>
+	<listitem><para>Actual position in input data (points to first unread char) 
+	in the case of input stream.</para></listitem>
+</varlistentry>
+<varlistentry>
+	<term><varname>type</varname></term>
+	<listitem><para>Member holding stream type - input or output.</para></listitem>
+</varlistentry>
+</variablelist></para>
+<para>Warning - internals of this data structure may change! Use it only through
+manipulation functions.
+</para>
+</refsect2>
+</refsect1>
+
+<refsect1 id="sstream_t.example"><title>Example</title>
+<programlisting>
+#include &lt;cds/sstr.h&gt;
+#include &lt;cds/serialize.h&gt;
+
+typedef struct {
+	str_t name;
+	int number;
+	char c;
+} test_t;
+
+int serialize_test_struct(sstream_t *store, test_t *t)
+{
+	if (serialize_str(store, &amp;t->name) != 0) return -1;
+	if (serialize_int(store, &amp;t->number) != 0) return -1;
+	if (serialize_char(store, &amp;t->c) != 0) return -1;
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	sstream_t store;
+	str_t data;
+	test_t a = { name: {"test A", 6}, number: 13, c: 'x' };
+	test_t b;
+
+	str_clear(&amp;data);
+
+	/* storing structure to the string */
+	
+	init_output_sstream(&amp;store, 256);
+	if (serialize_test_struct(&amp;store, &amp;a) == 0) {
+		if (get_serialized_sstream(&amp;store, &amp;data) != 0)
+			printf("can't get data\n");
+	}
+	else printf("can't serialize\n");
+	destroy_sstream(&amp;store);
+
+	/* loading structure from the string */
+	
+	init_input_sstream(&amp;store, data.s, data.len);
+	if (serialize_test_struct(&amp;store, &amp;b) == 0) {
+		printf("test_t = { %.*s, %d, %c }\n", 
+			FMT_STR(b.name), b.number, b.c);
+		
+		/* cleanup */
+		str_free_content(&amp;b.name);
+	}
+	else printf("can't deserialize\n");
+	destroy_sstream(&amp;store);
+
+	/* cleanup */
+	str_free_content(&amp;data);
+
+	return 0;
+}
+
+</programlisting>
+</refsect1>
+
+</refentry> 
+
+

+ 44 - 0
src/lib/cds/doc/str_clear.xml

@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="str_clear">
+
+<refmeta><refentrytitle>str_clear</refentrytitle>
+<manvolnum>3</manvolnum></refmeta>
+
+<refnamediv>
+<refname>str_clear</refname>
+<refpurpose>string initialization function</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+
+<funcsynopsisinfo>
+#include &lt;cds/sstr.h&gt;
+</funcsynopsisinfo>
+
+<funcprototype>
+  <funcdef>void <function>str_clear</function></funcdef>
+  <paramdef>str_t *<parameter>s</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Clears the given string - it sets string length 
+to 0 and pointer to data to NULL</para>
+</refsect1>
+
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="str_t"/>, <xref linkend="str_free"/>, <xref
+linkend="str_free_content"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 65 - 0
src/lib/cds/doc/str_dup.xml

@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="str_dup">
+
+<refmeta><refentrytitle>str_dup</refentrytitle>
+<manvolnum>3</manvolnum></refmeta>
+
+<refnamediv>
+<refname>str_dup</refname>
+<refname>str_dup_new</refname>
+<refname>str_dup_zt</refname>
+<refpurpose>string duplication functions</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+
+<funcsynopsisinfo>
+#include &lt;cds/sstr.h&gt;
+</funcsynopsisinfo>
+
+<funcprototype>
+  <funcdef>int <function>str_dup</function></funcdef>
+  <paramdef>str_t *<parameter>dst</parameter></paramdef>
+  <paramdef>const str_t *<parameter>src</parameter></paramdef>
+</funcprototype>
+
+<funcprototype>
+  <funcdef>int <function>str_dup_new</function></funcdef>
+  <paramdef>str_t *<parameter>dst</parameter></paramdef>
+  <paramdef>const char *<parameter>src</parameter></paramdef>
+</funcprototype>
+
+<funcprototype>
+  <funcdef>int <function>str_dup_zt</function></funcdef>
+  <paramdef>const str_t *<parameter>src</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>All these functions allocates necessary memory using
+<function>cds_malloc</function>.</para>
+
+<para><function>str_dup</function> takes as source the string given in
+<parameter>src</parameter></para>
+
+<para><function>str_dup_zt</function> takes as source zero-terminated string given in
+<parameter>src</parameter></para>
+
+<para><function>str_dup_new</function> works like <function>str_dup</function>
+with the difference, that it allocates not only the data buffer, but the 
+destination <structname>str_t</structname> structure too.
+</para>
+</refsect1>
+
+<refsect1><title>Return value</title>
+<para>All these functions return 0 if successful, nonzero otherwise.
+</para>
+</refsect1>
+
+</refentry> 
+

+ 44 - 0
src/lib/cds/doc/str_free.xml

@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="str_free">
+
+<refmeta><refentrytitle>str_free</refentrytitle>
+<manvolnum>3</manvolnum></refmeta>
+
+<refnamediv>
+<refname>str_free</refname>
+<refpurpose>destroys string</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+
+<funcsynopsisinfo>
+#include &lt;cds/sstr.h&gt;
+</funcsynopsisinfo>
+
+<funcprototype>
+  <funcdef>void <function>str_free</function></funcdef>
+  <paramdef>str_t *<parameter>s</parameter></paramdef>
+</funcprototype>
+
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>Frees string's data like str_free_content, 
+and the frees the <structname>str_t</structname> structure too.
+It uses <function>cds_free</function> as memory deallocation function.</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="str_t"/>, <xref linkend="str_free_content"/>, <xref linkend="str_clear"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 44 - 0
src/lib/cds/doc/str_free_content.xml

@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="str_free_content">
+
+<refmeta><refentrytitle>str_free_content</refentrytitle>
+<manvolnum>3</manvolnum></refmeta>
+
+<refnamediv>
+<refname>str_free_content</refname>
+<refpurpose>frees content of a string</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+
+<funcsynopsisinfo>
+#include &lt;cds/sstr.h&gt;
+</funcsynopsisinfo>
+
+<funcprototype>
+  <funcdef>void <function>str_free_content</function></funcdef>
+  <paramdef>str_t *<parameter>s</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+
+<para>Frees string's data if allocated
+(length &gt; 0 and pointer is not NULL) and clears its content like str_clear.
+It uses <function>cds_free</function> as memory deallocation function.</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para>
+<xref linkend="str_t"/>, <xref linkend="str_free"/>, <xref linkend="str_clear"/>
+<!-- references to other pages -->
+</para>
+</refsect1>
+
+</refentry> 
+

+ 84 - 0
src/lib/cds/doc/str_other.xml

@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="str_other">
+
+<refmeta><refentrytitle>helper functions</refentrytitle>
+<manvolnum>3</manvolnum></refmeta>
+
+<refnamediv>
+<refname>zt2str</refname>
+<refname>is_str_empty</refname>
+<refname>zt_strdup</refname>
+<refname>str_prefix</refname>
+<refname>str_strchr</refname>
+<refpurpose>various string helper functions</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv><funcsynopsis>
+
+<funcsynopsisinfo>
+#include &lt;cds/sstr.h&gt;
+</funcsynopsisinfo>
+
+<funcprototype>
+  <funcdef>str_t <function>zt2str</function></funcdef>
+  <paramdef>char *<parameter>s</parameter></paramdef>
+</funcprototype>
+
+<funcprototype>
+  <funcdef>int <function>is_str_empty</function></funcdef>
+  <paramdef>const str_t *<parameter>s</parameter></paramdef>
+</funcprototype>
+
+<funcprototype>
+  <funcdef>char *<function>zt_strdup</function></funcdef>
+  <paramdef>const char *<parameter>src</parameter></paramdef>
+</funcprototype>
+
+<funcprototype>
+  <funcdef>int <function>str_prefix</function></funcdef>
+  <paramdef>const str_t *<parameter>a</parameter></paramdef>
+  <paramdef>const str_t *<parameter>b</parameter></paramdef>
+</funcprototype>
+
+<funcprototype>
+  <funcdef>char *<function>str_strchr</function></funcdef>
+  <paramdef>const str_t *<parameter>s</parameter></paramdef>
+  <paramdef>char <parameter>c</parameter></paramdef>
+</funcprototype>
+
+</funcsynopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para><function>zt2str</function> converts zero terminated string to
+<structname>str_t</structname>. It doesn't copy data - both strings use the same
+buffer!
+</para>
+
+<para><function>is_str_empty</function> returns 1 if given string is empty (NULL
+pointer or length &lt; 1 or NULL pointer to string data)
+</para>
+
+<para><function>zt_strdup</function> duplicates given zero terminated string to
+another zero terminated string using cds_malloc function
+</para>
+
+<para><function>str_prefix</function> returns 0 if string
+<parameter>b</parameter> is prefix of <parameter>a</parameter>, nonzero
+otherwise (deprecated)
+</para>
+
+<para><function>str_strchr</function> searches for given character. It returns
+pointer to it in the string or NULL if not found.
+</para>
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para><xref linkend="str_t"/></para>
+</refsect1>
+
+</refentry> 
+

+ 48 - 0
src/lib/cds/doc/str_t.xml

@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="str_t">
+
+<refmeta><refentrytitle>str_t</refentrytitle>
+<manvolnum>3</manvolnum></refmeta>
+
+<refnamediv><refname>str_t</refname>
+<refpurpose>data structure for string representation</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv><synopsis>
+#include &lt;cds/sstr.h&gt;
+
+outside of SIP Express Router:
+
+typedef struct {
+	char *s;
+	int len;
+} str_t;
+
+inside of SIP Express Router:
+
+typedef str str_t;
+
+</synopsis></refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>This structure represents string. If compiled with SER it is defined using 
+SER string defined elsewhere: <programlisting>typedef str str_t;</programlisting>
+</para>
+<para>Otherwise it is defined as structure containing pointer to data buffer and
+length of this buffer.
+</para> 
+</refsect1>
+
+<refsect1><title>See Also</title>
+<para><xref linkend="str_dup"/>, <xref linkend="str_clear"/>, 
+<xref linkend="str_free_content"/>,	<xref linkend="str_free"/>
+<xref linkend="str_other"/>
+</para>
+</refsect1>
+
+</refentry> 
+

+ 23 - 0
src/lib/cds/doc/sync.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<reference id="sync">
+<title>Synchronization</title>
+
+<partintro>
+<para>Interprocess synchronization functions and data structures are 
+specific for SER. There are some wrapper macros for them in 
+the CDS library.
+</para>
+
+</partintro>
+
+<include xmlns="http://www.w3.org/2001/XInclude" href="cds_mutex_t.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="cds_mutex_init.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="cds_mutex_destroy.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="cds_mutex_lock.xml"/>
+<include xmlns="http://www.w3.org/2001/XInclude" href="cds_mutex_unlock.xml"/>
+
+</reference>

+ 226 - 0
src/lib/cds/dstring.c

@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <cds/dstring.h>
+#include <cds/memory.h>
+#include <cds/list.h>
+#include <cds/logger.h>
+
+#define get_current_buffer(dstr) (dstr)->last
+
+static dstr_buff_t *add_new_buffer(dstring_t *dstr)
+{
+	dstr_buff_t *buff = NULL;
+
+	/* e = dlink_element_alloc_pkg(sizeof(dstr_buff_t) + dstr->buff_size); */
+	/*	if (dstr->flags & DSTR_PKG_MEM)
+		buff = cds_malloc_pkg(sizeof(dstr_buff_t) + dstr->buff_size);
+	else
+		buff = cds_malloc(sizeof(dstr_buff_t) + dstr->buff_size);
+		*/
+	/*	buff = cds_malloc(sizeof(dstr_buff_t) + dstr->buff_size);*/
+	buff = cds_malloc_pkg(sizeof(dstr_buff_t) + dstr->buff_size);
+	if(buff) {
+		buff->len = dstr->buff_size;
+		buff->used = 0;
+		buff->next = NULL;
+		LINKED_LIST_ADD(dstr->first, dstr->last, buff);
+	} else
+		dstr->error = 1;
+	return buff;
+}
+
+int dstr_append(dstring_t *dstr, const char *s, int len)
+{
+	int size;
+	dstr_buff_t *buff;
+
+	/*	if (!dstr) return -1; */
+	if(dstr->error)
+		return -2;
+
+	if(len == 0)
+		return 0; /*append empty string*/
+
+	buff = get_current_buffer(dstr);
+	if(!buff)
+		buff = add_new_buffer(dstr);
+	while((len > 0) && (buff)) {
+		size = buff->len - buff->used;
+		if(size > len)
+			size = len;
+		memcpy(buff->data + buff->used, s, size);
+		buff->used += size;
+		len -= size;
+		s += size;
+		dstr->len += size;
+		if(len > 0)
+			buff = add_new_buffer(dstr);
+	}
+	if(!buff) {
+		dstr->error = 1;
+		return -1;
+	}
+	return 0;
+}
+
+int dstr_append_zt(dstring_t *dstr, const char *s)
+{
+	/*	if (!dstr) return -1; */
+	if(!s)
+		return 0; /*append empty string*/
+	return dstr_append(dstr, s, strlen(s));
+}
+
+int dstr_append_str(dstring_t *dstr, const str_t *s)
+{
+	/*	if (!dstr) return -1; */
+	if(!s)
+		return 0; /*append empty string*/
+	return dstr_append(dstr, s->s, s->len);
+}
+
+/* int dstr_get_data_length(dstring_t *dstr)
+{
+	if (!dstr) return 0;
+	else return dstr->len;
+} */
+
+int dstr_get_data(dstring_t *dstr, char *dst)
+{
+	dstr_buff_t *buff;
+
+	/* if (!dstr) return -1; */
+	if(dstr->error)
+		return -2; /* a previous operation returned error */
+
+	buff = dstr->first;
+	while(buff) {
+		memcpy(dst, buff->data, buff->used);
+		dst += buff->used;
+		buff = buff->next;
+	}
+	return 0;
+}
+
+int dstr_get_str(dstring_t *dstr, str_t *dst)
+{
+	int res = 0;
+
+	if(!dst)
+		return -1;
+	if(dstr->error) {
+		dst->s = NULL;
+		dst->len = 0;
+		return -2; /* a previous operation returned error */
+	}
+
+	dst->len = dstr_get_data_length(dstr);
+	if(dst->len > 0) {
+		dst->s = (char *)cds_malloc(dst->len);
+		if(!dst->s) {
+			res = -1;
+			dst->len = 0;
+		} else
+			res = dstr_get_data(dstr, dst->s);
+	} else {
+		dst->s = NULL;
+		dst->len = 0;
+	}
+
+	return res;
+}
+
+int dstr_get_str_pkg(dstring_t *dstr, str_t *dst)
+{
+	int res = 0;
+
+	if(!dst)
+		return -1;
+	if(dstr->error) {
+		dst->s = NULL;
+		dst->len = 0;
+		return -2; /* a previous operation returned error */
+	}
+
+	dst->len = dstr_get_data_length(dstr);
+	if(dst->len > 0) {
+		dst->s = (char *)cds_malloc_pkg(dst->len);
+		if(!dst->s) {
+			res = -1;
+			dst->len = 0;
+		} else
+			res = dstr_get_data(dstr, dst->s);
+	} else {
+		dst->s = NULL;
+		dst->len = 0;
+	}
+
+	return res;
+}
+
+int dstr_init(dstring_t *dstr, int buff_size)
+{
+	/* if (!dstr) return -1; */
+	dstr->buff_size = buff_size;
+	dstr->len = 0;
+	dstr->error = 0;
+	dstr->first = 0;
+	dstr->last = 0;
+	return 0;
+}
+
+int dstr_destroy(dstring_t *dstr)
+{
+	dstr_buff_t *e, *n;
+	/*	if (!dstr) return -1; */
+	/* dlink_destroy(&dstr->buffers); */
+	e = dstr->first;
+	while(e) {
+		n = e->next;
+		/*		if (dstr->flags & DSTR_PKG_MEM) cds_free_pkg(e);
+		else cds_free(e);*/
+		/*		cds_free(e);*/
+		cds_free_pkg(e);
+		e = n;
+	}
+	dstr->first = 0;
+	dstr->last = 0;
+	return 0;
+}
+
+/* int dstr_error(dstring_t *dstr)
+{
+	if (dstr) return dstr->error;
+	else return -1;
+}
+
+void dstr_clear_error(dstring_t *dstr)
+{
+	if (dstr) dstr->error = 0;
+}
+*/

+ 153 - 0
src/lib/cds/dstring.h

@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __DSTRING_H
+#define __DSTRING_H
+
+#include <cds/sstr.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+	/**
+ * \ingroup cds
+ * \defgroup cds_dstring Dynamic strings
+ *
+ * Dynamic strings were introduced to satisfy needs of presence
+ * modules when building presence documents.
+ *
+ * Dynamic string uses a list of buffers holding data.
+ * Buffers are allocated when needed - when there is not enough
+ * space in the last buffer. The whole result can be copied into one
+ * destination buffer with \ref dstr_get_data, \ref dstr_get_str
+ * or \ref dstr_get_str_pkg function.
+ *
+ * \todo Function with sprintf syntax which will help with
+ * readibility of code using dynamic strings.
+ * @{
+ * */
+
+	/** Buffer used by dynamic string.
+ *
+ * \todo 'len' and 'used' can be replaced by 'unused' member
+ * but it doesn't save too much */
+	typedef struct _dstr_buff_t
+	{
+		int len;				   /**< the buffer length */
+		int used;				   /**< already used bytes from buffer */
+		struct _dstr_buff_t *next; /**< pointer to next buffer in the list*/
+		char data[1];			   /** buffer data */
+	} dstr_buff_t;
+
+	/** Dynamic string structure. It is used
+ * for multiple appends of any string.
+ *
+ * \note There was an attempt to add flags for SHM/PKG memory using, ...
+ * but it shows that it slows down, thus they were removed and only the
+ * "most quick" version is used (rather two functions than one with param) */
+	typedef struct _dstring_t
+	{
+		/** pointer to the first buffer in the list */
+		dstr_buff_t *first;
+		/** pointer to the last buffer in the list */
+		dstr_buff_t *last;
+		/** the length of whole string */
+		int len;
+		/** predefined buffer size */
+		int buff_size;
+
+		/** a operation on this string was unsuccessful ->
+	 * all other operations will produce error */
+		int error;
+	} dstring_t;
+
+	/** Appends zero terminated string to dynamic string.
+ * \retval 0 if successful
+ * \retval negative on error */
+	int dstr_append_zt(dstring_t *dstr, const char *s);
+
+	/** Appends string with given length to dynamic string.
+ * \retval 0 if successful
+ * \retval negative on error */
+	int dstr_append(dstring_t *dstr, const char *s, int len);
+
+	/** Appends string to dynamic string.
+ * \retval 0 if successful
+ * \retval negative on error */
+	int dstr_append_str(dstring_t *dstr, const str_t *s);
+
+	/* int dstr_get_data_length(dstring_t *dstr); */
+
+	/** Returns data stored in dynamic string. It does NOT allocate
+ * space for them - it expects that the buffer is already allocated.
+ * \retval 0 if successful
+ * \retval negative on error */
+	int dstr_get_data(dstring_t *dstr, char *dst);
+
+	/** Returns data stored in dynamic string. It allocates space for
+ * them with cds_malloc (SER's shared memory).
+ * \retval 0 if successful
+ * \retval negative on error */
+	int dstr_get_str(dstring_t *dstr, str_t *dst);
+
+	/** Returns data stored in dynamic string. It allocates space for
+ * them with cds_malloc_pkg (SER's package memory).
+ * \retval 0 if successful
+ * \retval negative on error */
+	int dstr_get_str_pkg(dstring_t *dstr, str_t *dst);
+	/** Initializes dynamic string.
+ * \param dstr dynamic string to be initialized
+ * \param buff_size size of buffer used with this dynamic string
+ * \retval 0 if successful
+ * \retval negative on error */
+	int dstr_init(dstring_t *dstr, int buff_size);
+
+	/** Destroys dynamic string. It frees all allocated buffers. */
+	int dstr_destroy(dstring_t *dstr);
+
+/* returns nozero if error !!! */
+/* int dstr_error(dstring_t *dstr);
+void dstr_clear_error(dstring_t *dstr); */
+
+/** Macro returning length of data stored in dynamic string. */
+#define dstr_get_data_length(dstr) (dstr)->len
+
+/** Macro pointing to error in dynamic string. If set
+ * there was an error during a previous operation with
+ * this dynamic string. */
+#define dstr_error(dstr) (dstr)->error
+
+/** Macro for cleaning error flag in dynamic string. */
+#define dstr_clear_error(dstr) (dstr)->error = 0
+
+	/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 250 - 0
src/lib/cds/hash_table.c

@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <cds/hash_table.h>
+#include <cds/memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int ht_init(hash_table_t *ht, hash_func_t hash_func, key_cmp_func_t cmp_keys,
+		int size)
+{
+	if(!ht)
+		return -1;
+	if((!hash_func) || (!cmp_keys))
+		return -1;
+
+	ht->cslots = (ht_cslot_t *)cds_malloc(size * sizeof(ht_cslot_t));
+	if(!ht->cslots)
+		return -1;
+	memset(ht->cslots, 0, size * sizeof(ht_cslot_t));
+
+	ht->size = size;
+	ht->hash = hash_func;
+	ht->cmp = cmp_keys;
+
+	ht->find_cnt = 0;
+	ht->cmp_cnt = 0;
+	ht->nocmp_cnt = 0;
+	ht->missed_cnt = 0;
+	return 0;
+}
+
+void ht_destroy(hash_table_t *ht)
+{
+	ht_element_t *e, *n;
+	int i;
+
+	if(!ht)
+		return;
+	if(ht->cslots) {
+		for(i = 0; i < ht->size; i++) {
+			e = ht->cslots[i].first;
+			while(e) {
+				n = e->next;
+				cds_free(e);
+				e = n;
+			}
+		}
+		cds_free(ht->cslots);
+	}
+	ht->cslots = NULL;
+}
+
+int ht_add(hash_table_t *ht, ht_key_t key, ht_data_t data)
+{
+	int h;
+	ht_element_t *new_e;
+
+	if(!ht)
+		return -1;
+	new_e = (ht_element_t *)cds_malloc(sizeof(ht_element_t));
+	if(!new_e)
+		return -1;
+	new_e->next = NULL;
+	new_e->key = key;
+	new_e->data = data;
+
+	h = ht->hash(key) % ht->size;
+	if(h < 0)
+		h = -h;
+
+	if(!ht->cslots[h].last) {
+		ht->cslots[h].first = new_e;
+	} else {
+		ht->cslots[h].last->next = new_e;
+	}
+
+	ht->cslots[h].cnt++;
+	ht->cslots[h].last = new_e;
+	return 0;
+}
+
+ht_data_t ht_find(hash_table_t *ht, ht_key_t key)
+{
+	int h;
+	ht_element_t *e;
+
+	if(!ht)
+		return NULL;
+
+	ht->find_cnt++; //monitor
+
+	h = ht->hash(key) % ht->size;
+	if(h < 0)
+		h = -h;
+	e = ht->cslots[h].first;
+	if(!e)
+		ht->nocmp_cnt++; //monitor
+	while(e) {
+		ht->cmp_cnt++; //monitor
+		if(ht->cmp(e->key, key) == 0)
+			return e->data;
+		e = e->next;
+	}
+
+	ht->missed_cnt++; //monitor
+	return NULL;
+}
+
+ht_data_t ht_remove(hash_table_t *ht, ht_key_t key)
+{
+	int h;
+	ht_element_t *e, *p;
+	ht_data_t data;
+
+	if(!ht)
+		return NULL;
+	h = ht->hash(key) % ht->size;
+	if(h < 0)
+		h = -h;
+	e = ht->cslots[h].first;
+	p = NULL;
+	while(e) {
+		if(ht->cmp(e->key, key) == 0) {
+			if(p)
+				p->next = e->next;
+			else
+				ht->cslots[h].first = e->next;
+			ht->cslots[h].cnt--;
+			if(!e->next)
+				ht->cslots[h].last = p;
+			data = e->data;
+			cds_free(e);
+			return data;
+		}
+		p = e;
+		e = e->next;
+	}
+	return NULL;
+}
+
+void ht_get_statistic(hash_table_t *ht, ht_statistic_t *s)
+{
+	if(!s)
+		return;
+	if(!ht) {
+		s->find_cnt = 0;
+		s->cmp_cnt = 0;
+		s->nocmp_cnt = 0;
+		s->missed_cnt = 0;
+	} else {
+		s->find_cnt = ht->find_cnt;
+		s->cmp_cnt = ht->cmp_cnt;
+		s->nocmp_cnt = ht->nocmp_cnt;
+		s->missed_cnt = ht->missed_cnt;
+	}
+}
+
+void ht_clear_statistic(hash_table_t *ht)
+{
+	if(!ht)
+		return;
+
+	ht->find_cnt = 0;
+	ht->cmp_cnt = 0;
+	ht->nocmp_cnt = 0;
+	ht->missed_cnt = 0;
+}
+
+/* --------- hash table traversing functions -------- */
+
+ht_element_t *get_first_ht_element(hash_table_t *ht, ht_traversal_info_t *info)
+{
+	int i;
+	if(!info)
+		return NULL;
+	info->ht = ht;
+	info->current = NULL;
+	for(i = 0; i < ht->size; i++) {
+		if(ht->cslots[i].first) {
+			info->current = ht->cslots[i].first;
+			break;
+		}
+	}
+	info->slot_pos = i;
+	return info->current;
+}
+
+ht_element_t *get_next_ht_element(ht_traversal_info_t *info)
+{
+	int i;
+	if(!info)
+		return NULL;
+
+	if(info->current)
+		info->current = info->current->next;
+
+	if(info->current)
+		return info->current;
+	else {
+		for(i = info->slot_pos + 1; i < info->ht->size; i++) {
+			if(info->ht->cslots[i].first) {
+				info->current = info->ht->cslots[i].first;
+				break;
+			}
+		}
+		info->slot_pos = i;
+	}
+	return info->current;
+}
+
+/* --------- HASH functions -------- */
+
+unsigned int rshash(const char *str, unsigned int len)
+{
+	unsigned int b = 378551;
+	unsigned int a = 63689;
+	unsigned int hash = 0;
+	unsigned int i = 0;
+
+	for(i = 0; i < len; str++, i++) {
+		hash = hash * a + (*str);
+		a = a * b;
+	}
+
+	return (hash & 0x7FFFFFFF);
+}

+ 96 - 0
src/lib/cds/hash_table.h

@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __HASH_TABLE_H
+#define __HASH_TABLE_H
+
+typedef struct ht_statistic
+{
+	int find_cnt;
+	/** count of comparations during find operations */
+	int cmp_cnt;
+	/** count of finds which started in empty slot (-> no compares) */
+	int nocmp_cnt;
+	/** count of finds returning NULL */
+	int missed_cnt;
+} ht_statistic_t;
+
+typedef const void *ht_key_t;
+typedef void *ht_data_t;
+
+typedef unsigned int (*hash_func_t)(ht_key_t k);
+typedef int (*key_cmp_func_t)(ht_key_t a, ht_key_t b);
+
+typedef struct ht_element
+{
+	ht_key_t key;
+	ht_data_t data;
+	struct ht_element *next;
+} ht_element_t;
+
+typedef struct ht_cslot
+{
+	ht_element_t *first;
+	ht_element_t *last;
+	int cnt;
+} ht_cslot_t;
+
+typedef struct hash_table
+{
+	hash_func_t hash;
+	key_cmp_func_t cmp;
+	ht_cslot_t *cslots;
+	int size;
+
+	int find_cnt;
+	int cmp_cnt;
+	int nocmp_cnt;
+	int missed_cnt;
+} hash_table_t;
+
+int ht_init(hash_table_t *ht, hash_func_t hash_func, key_cmp_func_t cmp_keys,
+		int size);
+void ht_destroy(hash_table_t *ht);
+int ht_add(hash_table_t *ht, ht_key_t key, ht_data_t data);
+ht_data_t ht_remove(hash_table_t *ht, ht_key_t key);
+ht_data_t ht_find(hash_table_t *ht, ht_key_t key);
+void ht_get_statistic(hash_table_t *ht, ht_statistic_t *s);
+void ht_clear_statistic(hash_table_t *ht);
+
+/* traversing through whole hash table */
+typedef struct
+{
+	hash_table_t *ht;
+	int slot_pos;
+	ht_element_t *current;
+} ht_traversal_info_t;
+
+ht_element_t *get_first_ht_element(hash_table_t *ht, ht_traversal_info_t *info);
+ht_element_t *get_next_ht_element(ht_traversal_info_t *info);
+
+/* hash functions */
+unsigned int rshash(const char *str, unsigned int len);
+
+#endif

+ 64 - 0
src/lib/cds/list.h

@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __LIST_H
+#define __LIST_H
+
+#define DOUBLE_LINKED_LIST_ADD(first, last, e) \
+	do {                                       \
+		if(last)                               \
+			last->next = (e);                  \
+		else                                   \
+			first = (e);                       \
+		(e)->next = NULL;                      \
+		(e)->prev = last;                      \
+		last = (e);                            \
+	} while(0)
+
+#define DOUBLE_LINKED_LIST_REMOVE(first, last, e) \
+	do {                                          \
+		if((e)->next)                             \
+			(e)->next->prev = (e)->prev;          \
+		else                                      \
+			last = (e)->prev;                     \
+		if((e)->prev)                             \
+			(e)->prev->next = (e)->next;          \
+		else                                      \
+			first = (e)->next;                    \
+		(e)->next = NULL;                         \
+		(e)->prev = NULL;                         \
+	} while(0)
+
+#define LINKED_LIST_ADD(first, last, e) \
+	do {                                \
+		if(last)                        \
+			last->next = (e);           \
+		else                            \
+			first = (e);                \
+		(e)->next = NULL;               \
+		last = (e);                     \
+	} while(0)
+
+#endif

+ 70 - 0
src/lib/cds/logger.h

@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __LOGGER_H
+#define __LOGGER_H
+
+#ifndef SER
+
+#include <stdio.h>
+
+#define ERROR_LOG(a, args...) \
+	do {                      \
+		printf(a, ##args);    \
+	} while(0)
+#define DEBUG_LOG(a, args...) \
+	do {                      \
+		printf(a, ##args);    \
+	} while(0)
+#define TRACE_LOG(a, args...) \
+	do {                      \
+		printf(a, ##args);    \
+	} while(0)
+#define WARN_LOG(a, args...) \
+	do {                     \
+		printf(a, ##args);   \
+	} while(0)
+#define FLUSH_LOG()     \
+	do {                \
+		fflush(stdout); \
+	} while(0)
+
+#else
+/* TODO: logging for SER */
+
+#include "dprint.h"
+
+#define ERROR_LOG(a, args...) ERR(a, ##args)
+#define DEBUG_LOG(a, args...) DBG(a, ##args)
+/* #define TRACE_LOG(a,args...)		ERR(a,##args) */
+#define TRACE_LOG(fmt, args...) LOG(L_ERR, "TRACE: " LOC_INFO fmt, ##args)
+#define WARN_LOG(a, args...) WARN(a, ##args)
+#define FLUSH_LOG() \
+	do {            \
+	} while(0)
+
+#endif
+
+#endif

+ 127 - 0
src/lib/cds/memory.c

@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/* Common Data Structures - functions for memory allocation and deallocation
+ * and may be other memory management. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <cds/memory.h>
+#include <cds/sync.h>
+#include <cds/logger.h>
+
+#ifdef TRACE_CDS_MEMORY
+
+cds_mutex_t *mem_mutex = NULL;
+int *allocated_cnt = NULL;
+char *debug_file = "/tmp/mem.log";
+
+#define write_debug(s, args...)           \
+	if(1) {                               \
+		FILE *f = fopen(debug_file, "a"); \
+		if(f) {                           \
+			fprintf(f, s, ##args);        \
+			fclose(f);                    \
+		}                                 \
+		TRACE_LOG(s, ##args);             \
+	}
+
+void *debug_malloc(int size, const char *file, int line)
+{
+	void *m = NULL;
+	if(allocated_cnt && mem_mutex) {
+		cds_mutex_lock(mem_mutex);
+		(*allocated_cnt)++;
+		cds_mutex_unlock(mem_mutex);
+	}
+#ifdef SER
+	m = shm_malloc(size);
+#else
+	m = malloc(size);
+#endif
+	write_debug("ALLOC %p size %u from %s(%d)\n", m, size, file, line);
+	/* LOG(L_INFO, "%p\n", m); */
+	return m;
+}
+
+void debug_free(void *block, const char *file, int line)
+{
+	if(allocated_cnt && mem_mutex) {
+		cds_mutex_lock(mem_mutex);
+		(*allocated_cnt)--;
+		cds_mutex_unlock(mem_mutex);
+	}
+#ifdef SER
+	shm_free(block);
+#else
+	free(block);
+#endif
+	write_debug("FREE %p from %s(%d)\n", block, file, line);
+}
+
+void *debug_malloc_ex(unsigned int size)
+{
+	return debug_malloc(size, "<none>", 0);
+}
+
+void debug_free_ex(void *block)
+{
+	debug_free(block, "<none>", 0);
+}
+
+void cds_memory_trace_init()
+{
+	cds_mutex_init(mem_mutex);
+	allocated_cnt = cds_malloc(sizeof(int));
+	*allocated_cnt = 0;
+}
+
+void cds_memory_trace(char *dst, int dst_len)
+{
+	if(allocated_cnt && mem_mutex) {
+		cds_mutex_lock(mem_mutex);
+		snprintf(dst, dst_len, "There are allocated: %d memory blocks\n",
+				*allocated_cnt);
+		cds_mutex_unlock(mem_mutex);
+	}
+}
+
+#else /* ! CDS_TRACE_MEMORY */
+
+#ifdef SER
+
+void *shm_malloc_x(unsigned int size)
+{
+	return shm_malloc(size);
+}
+
+void shm_free_x(void *ptr)
+{
+	shm_free(ptr);
+}
+
+#endif
+
+#endif

+ 161 - 0
src/lib/cds/memory.h

@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __CDS_MEMORY_H
+#define __CDS_MEMORY_H
+
+/* #define TRACE_CDS_MEMORY */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+	/** \ingroup cds
+ * @{
+ *
+ * \defgroup cds_memory Memory management
+ *
+ * Memory operations are common for whole CDS library. Because it must work
+ together with SER's memory management and must work without it too, there are
+ wrapper macros for memory allocation/deallocation.
+ *
+ * @{ */
+
+	/* typedef void*(*cds_malloc_func)(unsigned int size);
+typedef void(*cds_free_func)(void *ptr);
+
+extern cds_malloc_func cds_malloc;
+extern cds_free_func cds_free;
+
+void cds_set_memory_functions(cds_malloc_func _malloc, cds_free_func _free); */
+
+	/** \def cds_malloc(s)
+ * Function/macro for memory allocation. Which function is choosen depends on
+ * SER and TRACE_CDS_MEMORY defines.
+ *
+ * When SER is defined shm_malloc is choosen, standard malloc otherwise. */
+
+	/** \def cds_free(p)
+ * Function/macro for memory deallocation. Which function is choosen depends
+ * on SER and TRACE_CDS_MEMORY defines.
+ *
+ * If SER is defined shm_free is choosen, standard free otherwise. */
+
+	/** \def cds_malloc_ptr
+ * Function/macro for memory allocation when pointer to function needed. Which
+ * function is choosen depends on SER and TRACE_CDS_MEMORY defines.
+ *
+ * If SER is defined shm_malloc is choosen, standard malloc otherwise.  */
+
+	/** \def cds_free_ptr
+ * Function/macro for memory deallocation when pointer to function needed.
+ * Which function is choosen depends on SER and TRACE_CDS_MEMORY defines.
+ *
+ * If SER is defined shm_free is choosen, standard free otherwise.  */
+
+	/** \def cds_malloc_pkg(s)
+ * Function/macro for 'local' memory allocation. Which function is choosen
+ * depends on SER and TRACE_CDS_MEMORY defines.
+ *
+ * When SER is defined pkg_malloc is choosen, standard malloc otherwise. */
+
+	/** \def cds_free_pkg(p)
+ * Function/macro for 'local' memory deallocation. Which function is choosen
+ * depends on SER and TRACE_CDS_MEMORY defines.
+ *
+ * When SER is defined pkg_free is choosen, standard free otherwise. */
+
+#ifdef TRACE_CDS_MEMORY
+
+	/** \internal Debugging variant of alloc function */
+	void *debug_malloc(int size, const char *file, int line);
+
+	/** \internal Debugging variant of free function */
+	void debug_free(void *block, const char *file, int line);
+
+	/** \internal Another debugging variant of alloc function - used when pointer
+ * to function needed. */
+	void *debug_malloc_ex(unsigned int size);
+
+	/** \internal Another debugging variant of free function - used when pointer to
+ * function needed. */
+	void debug_free_ex(void *block);
+
+	/* \internal Helper function for debugging - shows some debugging information about
+ * memory allocations (currently only the number of allocated blocks). */
+	void cds_memory_trace(char *dst, int dst_len);
+
+	/** \internal Helper function which is useful for memory debugging only - initializes
+ * internal variables for memory tracing */
+	void cds_memory_trace_init();
+
+#define cds_malloc(s) debug_malloc(s, __FILE__, __LINE__)
+#define cds_free(p) debug_free(p, __FILE__, __LINE__)
+#define cds_free_ptr debug_free_ex
+#define cds_malloc_ptr debug_malloc_ex
+#define cds_malloc_pkg(s) debug_malloc(s, __FILE__, __LINE__)
+#define cds_free_pkg(p) debug_free(p, __FILE__, __LINE__)
+
+#else /* !TRACE */
+
+#ifdef SER
+
+#include <mem/mem.h>
+#include <mem/shm_mem.h>
+
+void *shm_malloc_x(unsigned int size);
+void shm_free_x(void *ptr);
+
+#define cds_malloc(s) shm_malloc(s)
+#define cds_free(p) shm_free(p)
+#define cds_malloc_ptr shm_malloc_x
+#define cds_free_ptr shm_free_x
+#define cds_malloc_pkg(s) pkg_malloc(s)
+#define cds_free_pkg(p) pkg_free(p)
+
+#else /* !SER */
+
+#include <stdlib.h>
+
+#define cds_malloc(s) malloc(s)
+#define cds_free(p) free(p)
+#define cds_malloc_ptr malloc
+#define cds_free_ptr free
+#define cds_malloc_pkg(s) malloc(s)
+#define cds_free_pkg(p) free(p)
+
+#endif /* !SER */
+
+#endif /* !TRACE_CDS_MEMORY */
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @}
+ * @} */
+
+#endif

+ 238 - 0
src/lib/cds/msg_queue.c

@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <stdio.h>
+#include <cds/msg_queue.h>
+#include <cds/memory.h>
+#include <cds/ref_cntr.h>
+#include <cds/logger.h>
+
+mq_message_t *create_message_ex(int data_len)
+{
+	mq_message_t *m;
+	if(data_len < 0)
+		data_len = 0;
+	m = cds_malloc(data_len + sizeof(mq_message_t));
+	if(!m)
+		return NULL;
+	m->data_len = data_len;
+	m->data = (((char *)m) + sizeof(mq_message_t));
+	m->next = NULL;
+	m->allocation_style = message_allocated_with_data;
+	m->destroy_function = NULL;
+	return m;
+}
+
+mq_message_t *create_message(void *data, int data_len)
+{
+	mq_message_t *m;
+	/* if (data_len < 0) data_len = 0; */
+	m = cds_malloc(sizeof(mq_message_t));
+	if(!m)
+		return NULL;
+	m->data_len = data_len;
+	m->data = data;
+	m->next = NULL;
+	m->allocation_style = message_holding_data_ptr;
+	m->destroy_function = cds_free_ptr;
+	return m;
+}
+
+void init_message_ex(
+		mq_message_t *m, void *data, int data_len, destroy_function_f func)
+{
+	/* if (data_len < 0) data_len = 0; */
+	if(!m)
+		return;
+
+	m->data_len = data_len;
+	m->data = data;
+	m->next = NULL;
+	m->destroy_function = func;
+	m->allocation_style = message_holding_data_ptr;
+}
+
+void set_data_destroy_function(mq_message_t *msg, destroy_function_f func)
+{
+	if(msg)
+		msg->destroy_function = func;
+}
+
+void free_message(mq_message_t *msg)
+{
+	if(msg->destroy_function && msg->data)
+		msg->destroy_function(msg->data);
+	switch(msg->allocation_style) {
+		case message_allocated_with_data:
+			break;
+		case message_holding_data_ptr:
+			/* if (msg->data) cds_free(msg->data); */
+			break;
+	}
+	cds_free(msg);
+}
+
+int push_message(msg_queue_t *q, mq_message_t *m)
+{
+	if((!q) || (!m))
+		return -1;
+	m->next = NULL;
+
+	if(q->flags & MQ_USE_MUTEX)
+		cds_mutex_lock(&q->q_mutex);
+	if(q->last)
+		q->last->next = m;
+	else {
+		q->first = m;
+		q->last = m;
+	}
+	q->last = m;
+	if(q->flags & MQ_USE_MUTEX)
+		cds_mutex_unlock(&q->q_mutex);
+
+	return 0;
+}
+
+int mq_add_to_top(msg_queue_t *q, mq_message_t *m)
+{
+	if((!q) || (!m))
+		return -1;
+	m->next = NULL;
+
+	if(q->flags & MQ_USE_MUTEX)
+		cds_mutex_lock(&q->q_mutex);
+	m->next = q->first;
+	q->first = m;
+	if(!q->last)
+		q->last = m;
+	if(q->flags & MQ_USE_MUTEX)
+		cds_mutex_unlock(&q->q_mutex);
+
+	return 0;
+}
+
+mq_message_t *pop_message(msg_queue_t *q)
+{
+	mq_message_t *m;
+	if(!q)
+		return NULL;
+
+	if(q->flags & MQ_USE_MUTEX)
+		cds_mutex_lock(&q->q_mutex);
+	m = q->first;
+	if(m) {
+		if(q->first == q->last) {
+			q->first = NULL;
+			q->last = NULL;
+		} else
+			q->first = m->next;
+		m->next = NULL;
+	}
+	if(q->flags & MQ_USE_MUTEX)
+		cds_mutex_unlock(&q->q_mutex);
+
+	return m;
+}
+
+int is_msg_queue_empty(msg_queue_t *q)
+{
+	int res = 1;
+	if(q->flags & MQ_USE_MUTEX)
+		cds_mutex_lock(&q->q_mutex);
+	if(q->first)
+		res = 0;
+	if(q->flags & MQ_USE_MUTEX)
+		cds_mutex_unlock(&q->q_mutex);
+	return res;
+}
+
+int msg_queue_init(msg_queue_t *q)
+{
+	return msg_queue_init_ex(q, 1);
+}
+
+int msg_queue_init_ex(msg_queue_t *q, int synchronize)
+{
+	if(synchronize) {
+		cds_mutex_init(&q->q_mutex);
+		q->flags = MQ_USE_MUTEX;
+	} else
+		q->flags = 0;
+	q->first = NULL;
+	q->last = NULL;
+	return 0;
+}
+
+/** \internal Destroys all internal data of message queue and
+ * optionally frees it if no more references exist. */
+static inline void msg_queue_destroy_and_free(msg_queue_t *q, int do_free)
+{
+	mq_message_t *m, *n;
+	if(!q)
+		return;
+
+	if(q->flags & MQ_USE_REF_CNTR) {
+		if(!remove_reference(&q->ref)) {
+			/* this was NOT the last reference */
+			return;
+		}
+	}
+
+	if(q->flags & MQ_USE_MUTEX)
+		cds_mutex_lock(&q->q_mutex);
+	m = q->first;
+	while(m) {
+		n = m->next;
+		free_message(m);
+		m = n;
+	}
+	q->first = NULL;
+	q->last = NULL;
+	if(q->flags & MQ_USE_MUTEX) {
+		cds_mutex_unlock(&q->q_mutex);
+		cds_mutex_destroy(&q->q_mutex);
+	}
+	if(do_free)
+		cds_free(q);
+}
+
+void msg_queue_destroy(msg_queue_t *q)
+{
+	msg_queue_destroy_and_free(q, 0);
+}
+
+void msg_queue_free(msg_queue_t *q)
+{
+	msg_queue_destroy_and_free(q, 1);
+}
+
+void msg_queue_init_ref_cnt(msg_queue_t *q, reference_counter_group_t *grp)
+{
+	if(grp) {
+		init_reference_counter(grp, &q->ref);
+		q->flags |= MQ_USE_REF_CNTR;
+	} else
+		q->flags &= ~MQ_USE_REF_CNTR; /* don't use reference counter */
+}

+ 196 - 0
src/lib/cds/msg_queue.h

@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __MSG_QUEUE_H
+#define __MSG_QUEUE_H
+
+#include <cds/sync.h>
+#include <cds/ref_cntr.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+	/**
+ * \ingroup cds
+ * \defgroup cds_msg_queue Message Queue
+ *
+ * Message queue is a structure useful for sending data between processes.
+ * It can be synchronized via its own mutex or the synchronization can
+ * be left on caller. It can use reference counter which is useful
+ * when accessing dynamically allocated queue destroyed by its last user.
+ *
+ * \todo To meaningfully use reference counters it is needed to add
+ * function for adding new reference to message queue.
+ *
+ * \todo Introduce message types because it is often needed.
+ * @{
+ * */
+
+	typedef void (*destroy_function_f)(void *);
+
+	/** Structure holding message which can be put
+ * into message queue.
+ *
+ * There is a need to allow destroying the message without knowing its
+ * internals (destroying message queue with non-processed messages) and thus
+ * the destroy_function able to fully destroy whole data hold by message must
+ * be given. It is mostly needed to choose the function manually only for
+ * complex data with pointers which content need to be freed too.
+ * For simple structures it is set automatically during the message creation.
+ */
+	typedef struct _mq_message_t
+	{
+		/** pointer to data hold by the message */
+		void *data;
+		/** length of data hold by message */
+		int data_len;
+		/** pointer to next message in the queue - is used only when
+	 * message is in the queue */
+		struct _mq_message_t *next;
+		/** pointer to destroy function */
+		destroy_function_f destroy_function;
+		enum
+		{
+			message_allocated_with_data, /**< data are allocated together with message structure */
+			message_holding_data_ptr /**< message holds only pointer to data */
+		} allocation_style; /**< member describing the manner of data storage */
+		char data_buf
+				[1]; /**< data buffer used when data are allocated together with message */
+	} mq_message_t;
+
+
+/** Message queue flag meaning that internal queue mutex is used for
+ * synchronization. It is set during message queue initialization via \ref
+ * msg_queue_init or \ref msg_queue_init_ex. */
+#define MQ_USE_MUTEX 1
+
+/** Message queue flag meaning that reference counters are used.
+ * To set this flag is needed to call \ref msg_queue_init_ref_cnt with
+ * non-NULL group parameter. */
+#define MQ_USE_REF_CNTR 2
+
+	/** Message queue structure.
+ * Never access its members directly (they may change), always
+ * use interface functions!
+*/
+	typedef struct msg_queue
+	{
+		/** Reference counter. Need not to be used.
+	 * If you want to use reference counter to message queue you have
+	 * to call \ref msg_queue_init_ref_cnt function with not-NULL reference
+	 * counter group.*/
+		reference_counter_data_t ref;
+		/** Pointer to the first message in the queue. Messages are hold in
+	 * one way linked list, each message contains pointer to next one. */
+		mq_message_t *first;
+		/** Pointer to last message in the queue to speed up appending messages
+	 * into the queue.*/
+		mq_message_t *last;
+		/** Queue mutex - might not be initialized, depends on initialization
+	 * parameters */
+		cds_mutex_t q_mutex;
+		/** flags - see MQ_xxx constants */
+		unsigned int flags;
+	} msg_queue_t;
+
+/** Macro for accessing message data.
+ * It is better to use this macro than accessing internal members of
+ * the structure. */
+#define get_message_data(msg) (msg ? msg->data : NULL)
+/** Macro for determining message data length.
+ * It is better to use this macro than accessing internal members of
+ * the structure. */
+#define get_message_data_len(msg) (msg ? msg->data_len : 0)
+
+	/** The space for data is allocated in messages data
+ * (they are automatically freed!)! Pointer to allocated
+ * data bytes is in data variable in the message structure. */
+	mq_message_t *create_message_ex(int data_len);
+
+	/** Creates message holding data allocated using cds_malloc.
+ * Data must be allocated using cds_malloc or there must be
+ * set destroy function via \ref set_data_destroy_function
+ * because they are automatically freed by free_message! */
+	mq_message_t *create_message(void *data, int data_len);
+
+	/** Sets function which will be called by free_message to destroy data.
+ *
+ * This function may be useful when a complex structure with pointers is added
+ * as data parameter.  */
+	void set_data_destroy_function(mq_message_t *msg, destroy_function_f func);
+
+	/** Initializes message.
+ * If auto_free set, data must be allocated using cds_malloc and are
+ * automatically freed by free_message (and if msg_queue_destroy called) */
+	void init_message_ex(
+			mq_message_t *m, void *data, int data_len, destroy_function_f func);
+
+	/** Frees the message and data hold by the message. */
+	void free_message(mq_message_t *msg);
+
+	/** Put message into queue. */
+	int push_message(msg_queue_t *q, mq_message_t *m);
+
+	/** Remove message from queue. */
+	mq_message_t *pop_message(msg_queue_t *q);
+
+	/** Tests if message queue holds a message.
+ * \retval 1 if empty
+ * \retval 0 if NOT empty. */
+	int is_msg_queue_empty(msg_queue_t *q);
+
+	/** Initializes message queue with a mutex guarding queue operations. */
+	int msg_queue_init(msg_queue_t *q);
+
+	/** Initializes message queue. If synchronize is set it initializes
+ * a mutex guarding queue operations otherwise the message queue remains
+ * unsynchronized. */
+	int msg_queue_init_ex(msg_queue_t *q, int synchronize);
+
+	/** Initializes reference counter for given message queue
+ * \param grp specifies group of reference counters to use. The message
+ * queue will stop using the reference counter if NULL.
+ * \param q specifies the message queue */
+	void msg_queue_init_ref_cnt(msg_queue_t *q, reference_counter_group_t *grp);
+
+	/** Destroys message queue if no more references exist.
+ * This function destroys all message queue internal data but doesn't free
+ * the message queue itself. It can be useful for statically allocated queues
+ * or when allocated not using cds_malloc. */
+	void msg_queue_destroy(msg_queue_t *q);
+
+	/** Destroys and frees the message queue if no more references exist.
+ * It uses cds_free for freeing the memory. */
+	void msg_queue_free(msg_queue_t *q);
+
+	/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 55 - 0
src/lib/cds/ptr_vector.c

@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <cds/ptr_vector.h>
+#include <stdio.h>
+
+int ptr_vector_add(ptr_vector_t *vector, void *ptr)
+{
+	return vector_add(vector, &ptr);
+}
+
+void *ptr_vector_get(ptr_vector_t *vector, int index)
+{
+	void *ptr = NULL;
+	if(vector_get(vector, index, &ptr) != 0)
+		return NULL;
+	return ptr;
+}
+
+int ptr_vector_remove(ptr_vector_t *vector, int index)
+{
+	return vector_remove(vector, index);
+}
+
+void ptr_vector_destroy(ptr_vector_t *vector)
+{
+	return vector_destroy(vector);
+}
+
+int ptr_vector_init(vector_t *vector, int allocation_count)
+{
+	return vector_init(vector, sizeof(void *), allocation_count);
+}

+ 42 - 0
src/lib/cds/ptr_vector.h

@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __PTR_VECTOR_H
+#define __PTR_VECTOR_H
+
+#include <cds/vector.h>
+
+typedef vector_t ptr_vector_t;
+
+
+int ptr_vector_add(ptr_vector_t *vector, void *ptr);
+void *ptr_vector_get(ptr_vector_t *vector, int index);
+int ptr_vector_remove(ptr_vector_t *vector, int index);
+void ptr_vector_destroy(ptr_vector_t *vector);
+int ptr_vector_init(vector_t *vector, int allocation_count);
+
+#define ptr_vector_size(v) vector_size(v)
+
+#endif

+ 91 - 0
src/lib/cds/ref_cntr.c

@@ -0,0 +1,91 @@
+#include <cds/ref_cntr.h>
+#include <cds/logger.h>
+#include <cds/memory.h>
+
+/* functions for initialization and destruction */
+
+reference_counter_group_t *create_reference_counter_group(int mutex_cnt)
+{
+	reference_counter_group_t *g;
+	int i;
+
+	g = cds_malloc(sizeof(*g) + mutex_cnt * sizeof(cds_mutex_t));
+	if(!g) {
+		ERROR_LOG("can't allocate memory\n");
+		return NULL;
+	}
+
+	for(i = 0; i < mutex_cnt; i++) {
+		cds_mutex_init(&g->mutexes[i]);
+	}
+	g->mutex_to_assign = 0;
+	g->mutex_cnt = mutex_cnt;
+
+	return g;
+}
+
+void free_reference_counter_group(reference_counter_group_t *grp)
+{
+	int i;
+	if(grp) {
+		for(i = 0; i < grp->mutex_cnt; i++) {
+			cds_mutex_destroy(&grp->mutexes[i]);
+		}
+		cds_free(grp);
+	}
+}
+
+/* -------------------------------------------------------------------- */
+
+void init_reference_counter(
+		reference_counter_group_t *grp, reference_counter_data_t *ref)
+{
+	int m;
+	if(ref && grp) {
+		m = grp->mutex_to_assign;
+		ref->cntr = 1;
+		ref->mutex = grp->mutexes + m;
+		m = (m + 1) % grp->mutex_cnt; /* can't be less than zero */
+		grp->mutex_to_assign = m;
+	}
+}
+
+void add_reference(reference_counter_data_t *ref)
+{
+	if(ref) {
+		if(ref->mutex)
+			cds_mutex_lock(ref->mutex);
+		ref->cntr++;
+		if(ref->mutex)
+			cds_mutex_unlock(ref->mutex);
+	}
+}
+
+int get_reference_count(reference_counter_data_t *ref)
+{
+	int res = 0;
+	if(ref) {
+		if(ref->mutex)
+			cds_mutex_lock(ref->mutex);
+		res = ref->cntr;
+		if(ref->mutex)
+			cds_mutex_unlock(ref->mutex);
+	}
+	return res;
+}
+
+int remove_reference(reference_counter_data_t *ref)
+{
+	int res = 0;
+	if(ref) {
+		if(ref->mutex)
+			cds_mutex_lock(ref->mutex);
+		if(ref->cntr > 0)
+			ref->cntr--;
+		if(ref->cntr == 0)
+			res = 1;
+		if(ref->mutex)
+			cds_mutex_unlock(ref->mutex);
+	}
+	return res;
+}

+ 162 - 0
src/lib/cds/ref_cntr.h

@@ -0,0 +1,162 @@
+#ifndef __REFERENCE_CNTR_H
+#define __REFERENCE_CNTR_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+	/** \ingroup cds
+ * @{
+ *
+ * \defgroup cds_ref_cnt Reference counting
+ *
+ * Experimental functions for reference counting (to simplify
+ * this code elsewhere).
+ *
+ * Reference counter (\ref reference_counter_data_t) holds integer number which
+ * should be changed using functions \ref add_reference and \ref
+ * remove_reference. Using these functions is the number read/changed from
+ * locked section guarded by one mutex from a set of 'group mutexes'.
+ *
+ * Often used scenario:
+ * - list of structures, change in the list (adding, removing) is guarded by
+ *   one mutex,
+ * - each structure has reference counter, when the count is zero, the
+ *   structure can be removed from the list and freed
+ *
+ * Note that mutex for adding references is needed because references are not
+ * added from critical section guarded by main list mutex but can be added whenever.
+ *
+ * Typical usage:
+ * \code
+ * struct some_structure {
+ *     ...
+ *     reference_counter_data_t ref;
+ *     ...
+ * };
+ *
+ * reference_counter_group_t *some_grp;
+ *
+ * void init()
+ * {
+ *     some_grp = init_reference_counter_group(16);
+ * }
+ *
+ * void destroy()
+ * {
+ *     free_reference_counter_group(some_grp);
+ * }
+ *
+ * ...
+ *
+ * // adding a member:
+ * struct some_struct *ss = malloc(...);
+ * init_reference_counter(some_grp, &ss->ref);
+ * lock(list);
+ * add_to_list(ss);
+ * unlock(list);
+ *
+ * ...
+ * // adding a reference doesn't need to lock list
+ * // can be done only by a reference owner
+ * add_reference(&ss->ref);
+ *
+ * // releasing a member when not needed for caller and there is
+ * // no way how to obtain reference for released member
+ * // (no way how to find a member in list)
+ * if (remove_reference(&ss->ref)) {
+ *     // last reference removed
+ *     lock(list);
+ *     remove_from_list(ss);
+ *     free(ss);
+ *     unlock(list);
+ * }
+ *
+ * // or
+ * // releasing a member when not needed for caller and it is possible
+ * // to 'search' in the list (reference to released member can be somehow
+ * // obtained by inspecting the list):
+ * lock(list);
+ * if (remove_reference(&ss->ref)) {
+ *     // last reference removed
+ *     remove_from_list(ss);
+ *     free(ss);
+ * }
+ * unlock(list);
+ * \endcode
+ *
+ * \todo use atomic operations instead of locking
+ * @{ */
+
+#include <cds/sync.h>
+
+	/** Structure holding reference counter value. */
+	typedef struct
+	{
+		int cntr;			/**< counter value */
+		cds_mutex_t *mutex; /**< mutex assigned to this reference counter */
+	} reference_counter_data_t;
+
+	/** Structure holding information about group of reference counters.
+ * It holds array of mutexes which are assigned to single reference
+ * counters in this group. The assignment is done using an operation
+ * on pointer to reference_counter_data_t. */
+	typedef struct
+	{
+		int mutex_cnt; /**< number of mutexes for this group */
+
+		/** number of next mutex to be assigned - this member is NOT
+	 * read/changed from critical section but it doesn't matter
+	 * if it will be rewritten between processes because it is used
+	 * for load distributing only (the worst thing that can happen
+	 * is that the same mutex is assigned twice) */
+		int mutex_to_assign;
+		cds_mutex_t mutexes
+				[1]; /**< array of mutexes (allocated together with the structure)*/
+	} reference_counter_group_t;
+
+	/** Initializes reference counter - sets its value to 1.
+ * After call to this function, the caller is owner of first
+ * reference. From now it can call other functions like
+ * \ref add_reference or \ref remove_reference.
+ *
+ * This function initializes the mutex - it chooses one from
+ * group mutexes. The mutex can not be changed after this
+ * call (it is only for reading). */
+	void init_reference_counter(
+			reference_counter_group_t *grp, reference_counter_data_t *ref);
+
+	/** Adds reference - increments reference counter.
+ * This function can be called only by owner of at least one reference! */
+	void add_reference(reference_counter_data_t *ref);
+
+	/** Returns the value of reference counter. This function is mostly
+ * useless. */
+	int get_reference_count(reference_counter_data_t *ref);
+
+	/** Removes reference - decrements reference counter.
+ * This function can be called only by owner of at least one reference!
+ *
+ * \retval 0 if reference removed, but other references exist
+ * \retval 1 if removed last reference
+ *  */
+	int remove_reference(reference_counter_data_t *ref);
+
+	/** Creates and initializes group of reference counters. All reference
+ * counters 'belonging' to this group are using the same set of mutexes. */
+	reference_counter_group_t *create_reference_counter_group(int mutex_cnt);
+
+	/** Destroys all resources used by reference counter group.
+ * After this function call no reference counter initialized
+ * by this group can be used. */
+	void free_reference_counter_group(reference_counter_group_t *grp);
+
+	/** @}
+ * @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 131 - 0
src/lib/cds/rr_serialize.c

@@ -0,0 +1,131 @@
+#include <cds/memory.h>
+#include <cds/logger.h>
+#include <cds/rr_serialize.h>
+
+#ifdef SER
+
+static void rr_dup(rr_t **dst, rr_t *pkg_rr)
+{
+	rr_t *tmp = NULL;
+	int res;
+
+	tmp = pkg_rr;
+
+	while(pkg_rr) {
+		res = shm_duplicate_rr(dst, pkg_rr);
+		dst = &(*dst)->next;
+		pkg_rr = pkg_rr->next;
+	}
+	if(tmp)
+		free_rr(&tmp);
+}
+
+static int serialize_route(sstream_t *ss, rr_t **_r)
+{
+	int do_it = 0;
+	int res = 0;
+	if(is_input_sstream(ss)) { /* read route */
+		if(serialize_int(ss, &do_it) != 0)
+			return -1;
+		*_r = NULL;
+	} else { /* store route */
+		if(*_r)
+			do_it = 1;
+		else
+			do_it = 0;
+		if(serialize_int(ss, &do_it) != 0)
+			return -1;
+	}
+
+	if(do_it) {
+		str s;
+		if(*_r) {
+			s.s = (*_r)->nameaddr.name.s;
+			s.len = (*_r)->len;
+		}
+
+		res = serialize_str_ex(ss, &s) | res;
+		if(is_input_sstream(ss)) {
+			rr_t *pkg_rr = NULL;
+
+			parse_rr_body(s.s, s.len, &pkg_rr);
+			rr_dup(_r, pkg_rr);
+		}
+	}
+
+	return res;
+}
+
+int serialize_route_set(sstream_t *ss, rr_t **route_set)
+{
+	rr_t *r, *first = NULL, *last = NULL;
+	int res = 0;
+
+	if(is_input_sstream(ss)) { /* read */
+		do {
+			res = serialize_route(ss, &r) | res;
+			if(last)
+				last->next = r;
+			else
+				first = r;
+			last = r;
+			if(last) {
+				/* due to parsing rr (may be more rr_t than 1) */
+				while(last->next)
+					last = last->next;
+			}
+		} while(r);
+		*route_set = first;
+	} else { /* store */
+		r = *route_set;
+		while(r) {
+			serialize_route(ss, &r);
+			r = r->next;
+		}
+		r = NULL;
+		serialize_route(ss, &r); /* store terminating route */
+	}
+
+	return 0;
+}
+
+int route_set2str(rr_t *rr, str_t *dst_str)
+{
+	int res = 0;
+	sstream_t store;
+
+	init_output_sstream(&store, 256);
+
+	if(serialize_route_set(&store, &rr) != 0) {
+		ERROR_LOG("can't serialize route set\n");
+		res = -1;
+	} else {
+		if(get_serialized_sstream(&store, dst_str) != 0) {
+			ERROR_LOG("can't get serialized data\n");
+			res = -1;
+		}
+	}
+
+	destroy_sstream(&store);
+	return res;
+}
+
+int str2route_set(const str_t *s, rr_t **rr)
+{
+	int res = 0;
+	sstream_t store;
+
+	if(!s)
+		return -1;
+
+	init_input_sstream(&store, s->s, s->len);
+	if(serialize_route_set(&store, rr) != 0) {
+		ERROR_LOG("can't de-serialize route set\n");
+		res = -1;
+	}
+	destroy_sstream(&store);
+
+	return res;
+}
+
+#endif

+ 17 - 0
src/lib/cds/rr_serialize.h

@@ -0,0 +1,17 @@
+#ifndef __RR_SERIALIZE_H
+#define __RR_SERIALIZE_H
+
+#ifdef SER
+
+/* only within ser */
+#include <cds/sstr.h>
+#include <cds/serialize.h>
+#include <parser/parse_rr.h>
+
+int serialize_route_set(sstream_t *ss, rr_t **_r);
+int route_set2str(rr_t *rr, str_t *dst_str);
+int str2route_set(const str_t *s, rr_t **rr);
+
+#endif
+
+#endif

+ 93 - 0
src/lib/cds/ser_profile.c

@@ -0,0 +1,93 @@
+#ifdef SER
+#ifdef DO_PROFILE
+
+#include <cds/ser_profile.h>
+#include "dprint.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+DEFINE_PROF_POINT(pa_handle_subscription)
+DEFINE_PROF_POINT(pa_timer_presentity)
+DEFINE_PROF_POINT(pa_timer_pdomain)
+DEFINE_PROF_POINT(pa_response_generation)
+
+DEFINE_PROF_POINT(rls_handle_subscription)
+DEFINE_PROF_POINT(rls_timer_cb)
+DEFINE_PROF_POINT(rls_is_simple_rls_target)
+DEFINE_PROF_POINT(rls_query_rls_sevices)
+DEFINE_PROF_POINT(rls_query_resource_list)
+DEFINE_PROF_POINT(rls_have_flat_list)
+
+DEFINE_PROF_POINT(tem_timer_cb)
+DEFINE_PROF_POINT(tem_add_event)
+DEFINE_PROF_POINT(tem_remove_event)
+DEFINE_PROF_POINT(tem_do_step)
+
+DEFINE_PROF_POINT(b2b_handle_notify)
+
+void prof_trace(FILE *f, int pid, const char *s, profile_data_t a)
+{
+	fprintf(f, "%d\t%30s\t%d\t%u\n", pid, s, a.count, a.spent_time);
+	if(a.start_count != a.stop_count)
+		fprintf(f, "%s, %d start_count != stop_count (%d != %d)\n", s, pid,
+				a.start_count, a.stop_count);
+}
+
+void prof_trace_nested(FILE *f, int pid, const char *s, profile_data_t a)
+{
+	fprintf(f, "%d\t%29s*\t%d\t%u\n", pid, s, a.count, a.spent_time);
+	if(a.start_count != a.stop_count)
+		fprintf(f, "%s, %d start_count != stop_count (%d != %d)\n", s, pid,
+				a.start_count, a.stop_count);
+}
+
+#define trace(f, p, name) prof_trace(f, p, #name, prof_point(name))
+#define trace_nested(f, p, name) \
+	prof_trace_nested(f, p, #name, prof_point(name))
+
+void trace_func()
+{
+	pid_t p = getpid();
+	FILE *f;
+
+	f = fopen("/tmp/ser.profile", "at");
+	if(!f)
+		ERR("can't write into profile file\n");
+	else {
+
+		trace(f, p, pa_handle_subscription);
+		trace(f, p, pa_timer_pdomain);
+		trace_nested(f, p, pa_timer_presentity);
+		trace_nested(f, p, pa_response_generation);
+
+		trace(f, p, rls_handle_subscription);
+		trace(f, p, rls_timer_cb);
+		trace(f, p, rls_is_simple_rls_target);
+		trace(f, p, rls_query_rls_sevices);
+		trace(f, p, rls_query_resource_list);
+		trace(f, p, rls_have_flat_list);
+
+		/* 	trace_nested(f, p, tem_timer_cb); */
+		trace(f, p, tem_add_event);
+		trace(f, p, tem_remove_event);
+		trace(f, p, tem_do_step);
+
+		trace(f, p, b2b_handle_notify);
+
+		fprintf(f, "%d\t%30s\t1\t%u\n", p, "all", get_prof_time());
+
+		fclose(f);
+	}
+}
+
+void ser_profile_init()
+{
+	WARN("initializing profiler\n");
+	start_profile(trace_func);
+}
+
+#endif /* DO_PROFILE */
+
+#endif /* SER */

+ 48 - 0
src/lib/cds/ser_profile.h

@@ -0,0 +1,48 @@
+#ifndef __SER_PROFILE
+#define __SER_PROFILE
+
+#ifdef SER
+
+#ifdef DO_PROFILING
+
+#include <cds/simple_profile.h>
+
+/* declarations of watched profile points */
+
+DECLARE_PROF_POINT(pa_handle_subscription)
+DECLARE_PROF_POINT(pa_timer_presentity)
+DECLARE_PROF_POINT(pa_timer_pdomain)
+DECLARE_PROF_POINT(pa_response_generation)
+
+DECLARE_PROF_POINT(rls_handle_subscription)
+DECLARE_PROF_POINT(rls_timer_cb)
+DECLARE_PROF_POINT(rls_is_simple_rls_target)
+DECLARE_PROF_POINT(rls_query_rls_sevices)
+DECLARE_PROF_POINT(rls_query_resource_list)
+DECLARE_PROF_POINT(rls_have_flat_list)
+DECLARE_PROF_POINT(tem_timer_cb)
+DECLARE_PROF_POINT(tem_add_event)
+DECLARE_PROF_POINT(tem_remove_event)
+DECLARE_PROF_POINT(tem_do_step)
+
+DECLARE_PROF_POINT(b2b_handle_notify)
+
+/* do NOT use directly this */
+void ser_profile_init();
+
+#define SER_PROFILE_INIT ser_profile_init();
+
+#else /* don't profile */
+
+#define SER_PROFILE_INIT
+#define PROF_START(name)
+#define PROF_START_BODY(name)
+#define PROF_START_DECL(name)
+#define PROF_STOP(name)
+
+#endif /* DO_PROFILING */
+
+#endif /* SER */
+
+
+#endif

+ 288 - 0
src/lib/cds/serialize.c

@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <cds/serialize.h>
+#include <cds/logger.h>
+#include <stdio.h>
+
+int init_input_sstream(sstream_t *ss, char *data_in, int data_len)
+{
+	if(!ss)
+		return -1;
+
+	ss->type = sstream_in;
+	ss->in.len = data_len;
+	ss->in.s = data_in;
+	ss->in_pos = 0;
+	return 0;
+}
+
+int init_output_sstream(sstream_t *ss, int out_buff_resize)
+{
+	if(!ss)
+		return -1;
+
+	ss->type = sstream_out;
+	str_clear(&ss->in);
+	ss->in_pos = 0;
+	dstr_init(&ss->out, out_buff_resize);
+	return 0;
+}
+
+int get_serialized_sstream(sstream_t *ss, str_t *dst)
+{
+	if(ss->type == sstream_out)
+		return dstr_get_str(&ss->out, dst);
+	else
+		return -1; /* no output for input stream */
+}
+
+int get_serialized_sstream_data(sstream_t *ss, char *dst)
+{
+	if(ss->type == sstream_out)
+		return dstr_get_data(&ss->out, dst);
+	else
+		return -1; /* no output for input stream */
+}
+
+int get_serialized_sstream_len(sstream_t *ss)
+{
+	if(ss->type == sstream_out)
+		return dstr_get_data_length(&ss->out);
+	else
+		return 0; /* no output for input stream */
+}
+
+int sstream_get(sstream_t *ss, char *c)
+{
+	/* if (!is_input_sstream(ss)) return -1;  */ /* optimalization */
+	/* if (!c) return -1; */					 /* dangerous optimalization */
+	if(ss->in_pos < ss->in.len) {
+		*c = ss->in.s[ss->in_pos++];
+		return 0;
+	} else
+		return 1;
+}
+
+int sstream_put_str(sstream_t *ss, str_t *s)
+{
+	/* if (is_input_sstream(ss)) return -1;  */ /* dangerous optimalization */
+	return dstr_append_str(&ss->out, s);
+}
+
+/* returns a part of string of given length - it is NOT a copy !!! */
+int sstream_get_str_ex(sstream_t *ss, int len, str_t *dst)
+{
+	int l;
+	int res = 0;
+
+	if(!is_input_sstream(ss))
+		return -1;
+	if(!dst)
+		return -1;
+
+	if(len == 0) {
+		str_clear(dst);
+		return 0;
+	}
+
+	l = ss->in.len - ss->in_pos;
+	dst->s = ss->in.s + ss->in_pos;
+
+	if(len > l) {
+		dst->len = l;
+		res = 1; /* not whole requested string is returned ! */
+	} else
+		dst->len = len;
+	ss->in_pos += dst->len;
+
+	return 0;
+}
+
+/* returns a copy of string from input buffer */
+int sstream_get_str(sstream_t *ss, int len, str_t *dst)
+{
+	str_t tmp;
+	int res = sstream_get_str_ex(ss, len, &tmp);
+	if(res >= 0) {
+		res = str_dup(dst, &tmp);
+		if(res != 0)
+			str_clear(dst);
+	}
+	return res;
+}
+
+int sstream_put_zt(sstream_t *ss, const char *s)
+{
+	/* if (!is_input_sstream(ss)) return -1;  */ /* dangerous optimalization */
+	return dstr_append_zt(&ss->out, s);
+}
+
+int sstream_put(sstream_t *ss, const char *s, int len)
+{
+	/* if (!is_input_sstream(ss)) return -1;  */ /* dangerous optimalization */
+	return dstr_append(&ss->out, s, len);
+}
+
+void destroy_sstream(sstream_t *ss)
+{
+	if(ss->type == sstream_out)
+		dstr_destroy(&ss->out);
+}
+
+/*****************************************************************/
+
+int serialize_int(sstream_t *ss, int *num)
+{
+	char sep = ':';
+
+	if(!num)
+		return -1;
+
+	if(is_input_sstream(ss)) {
+		char c;
+		int first = 1;
+		int sign = 1; /* positive */
+
+		*num = 0;
+		while(sstream_get(ss, &c) == 0) {
+			if(c == sep)
+				break;
+			if((c >= '0') && (c <= '9'))
+				*num = 10 * (*num) + (c - '0');
+			else {
+				switch(c) {
+					case '-':
+						if(first)
+							sign = -1;
+						else
+							return -1;
+					case '+':
+						if(!first)
+							return -1;
+					default:
+						return -1; /* unknown character */
+				}
+			}
+			first = 0;
+		}
+		*num = sign * (*num);
+	} else {
+		char tmp[32];
+
+		sprintf(tmp, "%d%c", *num, sep);
+		sstream_put_zt(ss, tmp);
+	}
+	return 0;
+}
+
+int serialize_uint(sstream_t *ss, unsigned int *num)
+{
+	char sep = ':';
+
+	if(!num)
+		return -1;
+
+	if(is_input_sstream(ss)) {
+		char c;
+
+		*num = 0;
+		while(sstream_get(ss, &c) == 0) {
+			if(c == sep)
+				break;
+			if((c >= '0') && (c <= '9'))
+				*num = 10 * (*num) + (c - '0');
+			else
+				return -1; /* unknown character */
+		}
+	} else {
+		char tmp[32];
+
+		sprintf(tmp, "%u%c", *num, sep);
+		sstream_put_zt(ss, tmp);
+	}
+	return 0;
+}
+
+int serialize_str(sstream_t *ss, str_t *s)
+{
+	int res = 0;
+
+	if(!s)
+		return -1;
+
+	if(serialize_int(ss, &s->len) != 0)
+		return -1;
+	if(is_input_sstream(ss)) {
+		if(s->len == 0)
+			s->s = NULL;
+		else
+			res = sstream_get_str(ss, s->len, s); /* duplicates read string */
+	} else
+		res = sstream_put(ss, s->s, s->len);
+
+	return res;
+}
+
+int serialize_str_ex(sstream_t *ss, str_t *s)
+{
+	int res = 0;
+
+	if(!s)
+		return -1;
+
+	if(serialize_int(ss, &s->len) != 0)
+		return -1;
+	if(is_input_sstream(ss)) {
+		if(s->len == 0)
+			s->s = NULL;
+		else
+			res = sstream_get_str_ex(
+					ss, s->len, s); /* doesn't duplicate read string */
+	} else
+		res = sstream_put(ss, s->s, s->len);
+
+	return res;
+}
+
+int serialize_char(sstream_t *ss, char *c)
+{
+	if(!c)
+		return -1;
+	if(is_input_sstream(ss))
+		return sstream_get(ss, c);
+	else
+		return sstream_put(ss, c, 1);
+}
+
+int serialize_uchar(sstream_t *ss, unsigned char *c)
+{
+	if(!c)
+		return -1;
+	if(is_input_sstream(ss))
+		return sstream_get(ss, (char *)c);
+	else
+		return sstream_put(ss, (char *)c, 1);
+}

+ 91 - 0
src/lib/cds/serialize.h

@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __SERIALIZE_H
+#define __SERIALIZE_H
+
+/* serialization/deserialization data structures and functions */
+
+#include <cds/dstring.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+	typedef struct
+	{
+		dstring_t out; /* output string */
+		str_t in;	   /* input string */
+		int in_pos;	   /* position in input */
+		enum
+		{
+			sstream_in,
+			sstream_out
+		} type;
+	} sstream_t;
+
+#define is_input_sstream(ss) (ss->type == sstream_in)
+
+	int init_input_sstream(sstream_t *ss, char *data_in, int data_len);
+	int init_output_sstream(sstream_t *ss, int out_buff_resize);
+
+	/** returns serialized data as newly allocated string in shared memory */
+	int get_serialized_sstream(sstream_t *ss, str_t *dst);
+
+	/** returns the length of serialized data */
+	int get_serialized_sstream_len(sstream_t *ss);
+
+	/** copies serialized data into given buffer */
+	int get_serialized_sstream_data(sstream_t *ss, char *dst);
+
+	void destroy_sstream(sstream_t *ss);
+
+	int sstream_put(sstream_t *ss, const char *s, int len);
+	int sstream_put_str(sstream_t *ss, str_t *s);
+	int sstream_put_zt(sstream_t *ss, const char *s);
+
+	int sstream_get(sstream_t *ss, char *c);
+
+	/* returns a part of string of given length - it is NOT a copy !!! */
+	int sstream_get_str_ex(sstream_t *ss, int len, str_t *dst);
+
+	/* returns a copy of string from input buffer */
+	int sstream_get_str(sstream_t *ss, int len, str_t *dst);
+
+
+	int serialize_int(sstream_t *ss, int *num);
+	int serialize_uint(sstream_t *ss, unsigned int *num);
+	int serialize_char(sstream_t *ss, char *c);
+	int serialize_uchar(sstream_t *ss, unsigned char *c);
+	int serialize_str(sstream_t *ss, str_t *s);
+	int serialize_str_ex(
+			sstream_t *ss, str_t *s); /* doesn't duplicate read strings */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 87 - 0
src/lib/cds/simple_profile.c

@@ -0,0 +1,87 @@
+#include <stdio.h>
+#include <cds/simple_profile.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <string.h>
+
+#define trace_signal SIGTRAP
+
+typedef void (*_sig_t)(int);
+
+unsigned int tick_counter = 0;
+static struct sigaction old_sigprof_action;
+static _sig_t old_sigx_action;
+static int initialized = 0;
+static trace_f trace_function = NULL;
+
+int reset_timer()
+{
+	struct itimerval tv;
+	int res;
+
+	tv.it_interval.tv_sec = 0;
+	tv.it_interval.tv_usec = 1000;
+	/*tv.it_interval.tv_usec = 10 * 1000; */
+	tv.it_value.tv_sec = tv.it_interval.tv_sec;
+	tv.it_value.tv_usec = tv.it_interval.tv_usec;
+
+	res = setitimer(ITIMER_PROF, &tv, NULL);
+
+	return res;
+}
+
+void prof_handler(int a, siginfo_t *info, void *b)
+{
+	tick_counter++;
+	/*	LOG(L_ERR, "PROFILE HANDLER called\n"); */
+	/* reset_timer(); */
+}
+
+void trace_handler(int a)
+{
+	if(trace_function)
+		trace_function();
+}
+
+int start_profile(trace_f tf)
+{
+	struct sigaction action;
+	int res;
+
+	if(initialized)
+		return 1;
+	initialized = 1;
+	trace_function = tf;
+
+	memset(&action, 0, sizeof(action));
+	action.sa_sigaction = prof_handler;
+	sigemptyset(&action.sa_mask);
+	action.sa_flags = SA_SIGINFO;
+	res = sigaction(SIGPROF, &action, &old_sigprof_action);
+	if(res != 0) {
+		/* ERROR_LOG("can't set signal handle (%d)\n", res);*/
+		return -1;
+	}
+
+	old_sigx_action = signal(trace_signal, &trace_handler);
+
+	res = reset_timer();
+	if(res != 0) {
+		/* ERROR_LOG("can't set itimer (%d)\n", res);*/
+		signal(trace_signal, old_sigx_action);
+		sigaction(SIGPROF, &old_sigprof_action, NULL);
+		return -1;
+	}
+
+	return 0;
+}
+
+int stop_profile()
+{
+	if(initialized) {
+		initialized = 0;
+		signal(trace_signal, old_sigx_action);
+		return sigaction(SIGPROF, &old_sigprof_action, NULL);
+	} else
+		return -1;
+}

+ 52 - 0
src/lib/cds/simple_profile.h

@@ -0,0 +1,52 @@
+#ifndef __SIMPLE_PROFILE_H
+#define __SIMPLE_PROFILE_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+	typedef void (*trace_f)();
+
+	int start_profile(trace_f tf);
+	int stop_profile();
+
+	/* do NOT use this directly ! */
+	extern unsigned int tick_counter;
+
+#define get_prof_time() tick_counter
+
+	typedef struct
+	{
+		int count;
+		int start_count, stop_count;
+		unsigned int spent_time;
+	} profile_data_t;
+
+#define DEFINE_PROF_POINT(name) profile_data_t prof_##name = {0, 0, 0};
+#define DECLARE_PROF_POINT(name) extern profile_data_t prof_##name;
+
+#define prof_point(name) prof_##name
+#define PROF_START_DECL(name) int _prof_act_##name;
+#define PROF_START_BODY(name)       \
+	prof_point(name).count++;       \
+	prof_point(name).start_count++; \
+	_prof_act_##name = get_prof_time();
+
+#define PROF_START(name)            \
+	int _prof_act_##name;           \
+	prof_point(name).count++;       \
+	prof_point(name).start_count++; \
+	_prof_act_##name = get_prof_time();
+
+#define PROF_STOP(name)            \
+	prof_point(name).stop_count++; \
+	prof_point(name).spent_time += get_prof_time() - _prof_act_##name;
+
+#define prof_return(a, val) prof_stop(a) return val;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 158 - 0
src/lib/cds/sip_utils.c

@@ -0,0 +1,158 @@
+#ifdef SER
+
+#include <cds/sip_utils.h>
+#include <cds/sstr.h>
+#include <parser/parse_expires.h>
+#include <parser/parse_subscription_state.h>
+#include <parser/parser_f.h>
+#include <parser/parse_to.h>
+#include <trim.h>
+
+
+int get_expiration_value(struct sip_msg *m, int *value)
+{
+	exp_body_t *expires = NULL;
+	int res = 1;
+
+	if(parse_headers(m, HDR_EXPIRES_F, 0) == -1) {
+		/* can't parse expires header */
+		return -1;
+	}
+	if(m->expires) {
+		if(parse_expires(m->expires) < 0) {
+			return -1;
+		}
+
+		res = 0;
+		expires = (exp_body_t *)m->expires->parsed;
+		if(expires)
+			if(expires->valid && value)
+				*value = expires->val;
+	}
+	/* ERR("subscription will expire in %d secs\n", e); */
+	return res;
+}
+
+int is_terminating_notify(struct sip_msg *m)
+{
+	subscription_state_t *ss;
+
+	if(parse_headers(m, HDR_SUBSCRIPTION_STATE_F, 0) == -1) {
+		ERR("Error while parsing headers\n");
+		return 0; /* ignore */
+	}
+	if(!m->subscription_state) {
+		ERR("Invalid NOTIFY request (without Subscription-State)\n");
+		return 0; /* ignore */
+	}
+	if(parse_subscription_state(m->subscription_state) < 0) {
+		ERR("can't parse Subscription-State\n");
+		return 0; /* ignore */
+	}
+	ss = (subscription_state_t *)m->subscription_state->parsed;
+	if(!ss) {
+		ERR("invalid Subscription-State\n");
+		return 0; /* ignore */
+	}
+
+	if(ss->value == ss_terminated)
+		return 1;
+
+	return 0;
+}
+
+static inline int contains_extension_support(
+		struct hdr_field *h, str *extension)
+{
+	/* "parses" Supported header and looks for extension */
+	str s, val;
+	char *c;
+
+	if(!h)
+		return 0;
+
+	s = h->body;
+	while(s.len > 0) {
+		c = find_not_quoted(&s, ',');
+		if(c) {
+			val.s = s.s;
+			val.len = c - val.s;
+			trim(&val);
+			if(str_case_equals(&val, extension) == 0)
+				return 1;
+			s.len = s.len - (c - s.s) - 1;
+			s.s = c + 1;
+		} else {
+			trim(&s);
+			if(str_case_equals(&s, extension) == 0)
+				return 1;
+			break;
+		}
+	}
+	return 0;
+}
+
+int supports_extension(struct sip_msg *m, str *extension)
+{
+	/* walk through all Supported headers */
+	struct hdr_field *h;
+	int res;
+
+	/* we need all Supported headers */
+	res = parse_headers(m, HDR_EOH_F, 0);
+	if(res == -1) {
+		ERR("Error while parsing headers (%d)\n", res);
+		return 0; /* what to return here ? */
+	}
+
+	h = m->supported;
+	while(h) {
+		if(h->type == HDR_SUPPORTED_T) {
+			if(contains_extension_support(h, extension))
+				return 1;
+		}
+		h = h->next;
+	}
+	return 0;
+}
+
+int requires_extension(struct sip_msg *m, str *extension)
+{
+	/* walk through all Require headers */
+	struct hdr_field *h;
+	int res;
+
+	/* we need all Require headers */
+	res = parse_headers(m, HDR_EOH_F, 0);
+	if(res == -1) {
+		ERR("Error while parsing headers (%d)\n", res);
+		return 0; /* what to return here ? */
+	}
+
+	h = m->require;
+	while(h) {
+		if(h->type == HDR_REQUIRE_T) {
+			if(contains_extension_support(h, extension))
+				return 1;
+		}
+		h = h->next;
+	}
+	return 0;
+}
+
+/**
+ * Verifies presence of the To-tag in message. Returns 1 if
+ * the tag is present, 0 if not, -1 on error.
+ */
+int has_to_tag(struct sip_msg *_m)
+{
+	struct to_body *to = (struct to_body *)_m->to->parsed;
+	if(!to)
+		return -1;
+	if(to->tag_value.len > 0)
+		return 1;
+	return 0;
+}
+
+
+#endif

+ 31 - 0
src/lib/cds/sip_utils.h

@@ -0,0 +1,31 @@
+#ifndef __COMMON_SIP_UTILS_H
+#define __COMMON_SIP_UTILS_H
+
+#ifdef SER /* SER only helper routines */
+
+#include <parser/msg_parser.h>
+
+/* returns negative value on error, positive when message contains
+ * no Expires header and 0 if everything ok */
+int get_expiration_value(struct sip_msg *m, int *value);
+
+/* returns 1 if the message has Subscription-Status: terminated (hack!) */
+int is_terminating_notify(struct sip_msg *m);
+
+/* returns 1 if given extension is in Supported headers,
+ * 0 if not or an error occurred while parsing */
+int supports_extension(struct sip_msg *m, str *extension);
+
+/* returns 1 if given extension is in Require headers,
+ * 0 if not or an error occurred while parsing */
+int requires_extension(struct sip_msg *m, str *extension);
+
+/**
+ * Verifies presence of the To-tag in message. Returns 1 if
+ * the tag is present, 0 if not, -1 on error.
+ */
+int has_to_tag(struct sip_msg *_m);
+
+#endif
+
+#endif

+ 367 - 0
src/lib/cds/sstr.c

@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <cds/sstr.h>
+#include <cds/memory.h>
+#include <cds/dstring.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <cds/logger.h>
+
+/** returns 1 if the string is empty */
+int is_str_empty(const str_t *s)
+{
+	if(!s)
+		return 1;
+	if((!s->s) || (s->len < 1))
+		return 1;
+	return 0;
+}
+
+int str_cmp_zt(const str_t *a, const char *b)
+{
+	int i;
+
+	if(!a) {
+		if(b)
+			return 1;
+		else
+			return 0;
+	}
+
+	for(i = 0; (i < a->len) && (b[i]); i++) {
+		if(a->s[i] < b[i])
+			return -1;
+		if(a->s[i] > b[i])
+			return 1;
+	}
+	if(i < a->len)
+		return 1;
+	return 0;
+}
+
+int str_prefix(const str_t *a, const str_t *b)
+{
+	int i;
+	if(!b)
+		return 0;
+	if(!a)
+		return -1;
+
+	if(b->len > a->len)
+		return -1;
+	for(i = 0; i < b->len; i++) {
+		if(a->s[i] != b->s[i])
+			return -1;
+	}
+	return 0;
+}
+
+str_t zt2str(char *str)
+{
+	str_t s;
+
+	s.s = str;
+	if(str)
+		s.len = strlen(str);
+	else
+		s.len = 0;
+	return s;
+}
+
+int str_dup_dbg(str_t *dst, const str_t *src, const char *file, int line)
+{
+	if(!dst)
+		return -1;
+
+	dst->len = 0;
+	dst->s = NULL;
+	if(!src)
+		return 0;
+	if((!src->s) || (src->len < 1))
+		return 0;
+
+	/* ERROR_LOG("can't allocate memory (%d bytes)\n", src->len); */
+	DEBUG_LOG("str_dup called from %s:%d\n", file, line);
+	dst->s = cds_malloc(src->len);
+	if(!dst->s) {
+		/* ERROR_LOG("can't allocate memory (%d bytes)\n", src->len); */
+		return -1;
+	}
+	memcpy(dst->s, src->s, src->len);
+	dst->len = src->len;
+	return 0;
+}
+
+int str_dup_impl(str_t *dst, const str_t *src)
+{
+	if(!dst)
+		return -1;
+
+	dst->len = 0;
+	dst->s = NULL;
+	if(!src)
+		return 0;
+	if((!src->s) || (src->len < 1))
+		return 0;
+
+	dst->s = cds_malloc(src->len);
+	if(!dst->s) {
+		/* ERROR_LOG("can't allocate memory (%d bytes)\n", src->len); */
+		return -1;
+	}
+	memcpy(dst->s, src->s, src->len);
+	dst->len = src->len;
+	return 0;
+}
+
+str_t *str_dup_new(const str_t *src)
+{
+	str_t *dst = cds_malloc(sizeof(str_t));
+	if(dst)
+		str_dup(dst, src);
+	return dst;
+}
+
+int str_dup_zt(str_t *dst, const char *src)
+{
+	int len;
+	if(!dst)
+		return -1;
+
+	dst->len = 0;
+	dst->s = NULL;
+	if(!src)
+		return 0;
+	len = strlen(src);
+	if(len < 1)
+		return 0;
+
+	dst->s = cds_malloc(len);
+	if(!dst->s)
+		return -1;
+	memcpy(dst->s, src, len);
+	dst->len = len;
+	return 0;
+}
+
+char *zt_strdup(const char *src)
+{
+	int len;
+	char *dst;
+
+	len = strlen(src);
+	if(len < 0)
+		return NULL;
+
+	dst = cds_malloc(len + 1);
+	if(dst)
+		memcpy(dst, src, len + 1);
+	return dst;
+}
+
+int str_nocase_equals(const str_t *a, const str_t *b)
+{
+	int i;
+
+	if(!a) {
+		if(!b)
+			return 0;
+		else
+			return (b->len == 0) ? 0 : 1;
+	}
+	if(!b)
+		return (a->len == 0) ? 0 : 1;
+	if(a->len != b->len)
+		return 1;
+
+	for(i = 0; i < a->len; i++)
+		if(tolower(a->s[i]) != tolower(b->s[i]))
+			return 1;
+	return 0;
+}
+
+int str_case_equals(const str_t *a, const str_t *b)
+{
+	int i;
+
+	if(!a) {
+		if(!b)
+			return 0;
+		else
+			return (b->len == 0) ? 0 : 1;
+	}
+	if(!b)
+		return (a->len == 0) ? 0 : 1;
+	if(a->len != b->len)
+		return 1;
+
+	for(i = 0; i < a->len; i++)
+		if(a->s[i] != b->s[i])
+			return 1;
+	return 0;
+}
+
+/* void str_free_content(str_t *s)
+{
+	if (!s) return;
+	if ((s->len > 0) && (s->s)) cds_free(s->s);
+	s->len = 0;
+	s->s = NULL;
+}
+
+void str_free(str_t *s)
+{
+	if (s) {
+		str_free_content(s);
+		cds_free(s);
+	}
+}
+
+void str_clear(str_t *s)
+{
+	if (s) {
+		s->s = NULL;
+		s->len = 0;
+	}
+} */
+
+char *str_strchr(const str_t *s, char c)
+{
+	if(s) {
+		int i;
+		for(i = 0; i < s->len; i++)
+			if(s->s[i] == c)
+				return s->s + i;
+	}
+	return NULL;
+}
+
+char *str_str(const str_t *s, const str_t *search_for)
+{
+	int i, j;
+
+	if(is_str_empty(search_for))
+		return s->s;
+	if(is_str_empty(s))
+		return NULL;
+
+	if(search_for->len > s->len)
+		return NULL;
+
+	j = 0;
+	i = 0;
+	while(i < s->len) {
+		if(s->s[i] == search_for->s[j]) {
+			j++;
+			i++;
+			if(j == search_for->len)
+				return s->s + i - j;
+		} else {
+			i = i - j + 1;
+			j = 0;
+		}
+	}
+	return NULL;
+}
+
+/* creates new string as concatenation of a and b */
+int str_concat(str_t *dst, str_t *a, str_t *b)
+{
+	int al;
+	int bl;
+
+	if(!dst)
+		return -1;
+
+	al = str_len(a);
+	bl = str_len(b);
+
+	dst->len = al + bl;
+	if(dst->len > 0) {
+		dst->s = (char *)cds_malloc(dst->len);
+		if(!dst->s) {
+			dst->len = 0;
+			return -1;
+		}
+	} else {
+		dst->s = NULL;
+		dst->len = 0;
+		return 0;
+	}
+
+	if(al)
+		memcpy(dst->s, a->s, al);
+	if(bl)
+		memcpy(dst->s + al, b->s, bl);
+
+	return 0;
+}
+
+int replace_str(
+		const str_t *src, str_t *dst, const str_t *sample, const str_t *value)
+{
+	str_t s;
+	char *c;
+	dstring_t str;
+	int res, len;
+
+	/* if (!dst) return -1;
+	 if (!src) {
+		str_clear(dst);
+		return -1;
+	} */
+
+	if(is_str_empty(sample)) {
+		str_clear(dst);
+		return -1;
+	}
+
+	if(is_str_empty(src)) {
+		str_clear(dst);
+		return 0;
+	}
+
+	s = *src;
+	dstr_init(&str, src->len + 32);
+	do {
+		c = str_str(&s, sample);
+		if(c) {
+			len = c - s.s;
+			dstr_append(&str, s.s, len);
+			dstr_append_str(&str, value);
+			s.len = s.len - len - sample->len;
+			s.s = c + sample->len;
+			if(s.len <= 0)
+				break;
+		} else
+			dstr_append_str(&str, &s);
+	} while(c);
+
+	res = dstr_get_str(&str, dst);
+	dstr_destroy(&str);
+	return res;
+}

+ 170 - 0
src/lib/cds/sstr.h

@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __SIMPLE_STR_H
+#define __SIMPLE_STR_H
+
+#include <cds/memory.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* If compiled for SER, use ser internal strings ! */
+#ifdef SER
+
+#include "str.h"
+	typedef str str_t;
+
+#else
+
+typedef struct
+{
+	char *s;
+	int len;
+} str_t;
+
+#define STR_STATIC_INIT(v) \
+	{                      \
+		(v), sizeof(v) - 1 \
+	}
+
+#endif
+
+#define FMT_STR(str) (str).len, ((str).s ? (str).s : "")
+
+#define str_len(ptr) ((ptr) ? (ptr)->len : 0)
+
+	/** translate zero-terminated string to str_t (both uses the input buffer!)*/
+	str_t zt2str(char *str);
+
+	/** returns 1 if the string is empty */
+	int is_str_empty(const str_t *s);
+
+	/** duplicate string into given destination (data region is newly allocated) */
+	int str_dup_impl(str_t *dst, const str_t *src);
+	int str_dup_dbg(str_t *dst, const str_t *src, const char *file, int line);
+/*#define str_dup(dst,src)	str_dup_dbg(dst,src,__FILE__,__LINE__)*/
+#define str_dup(dst, src) str_dup_impl(dst, src)
+
+
+	/** duplicate string into newly allocated destination (data and str structure are newly allocated) */
+	str_t *str_dup_new(const str_t *src);
+
+	/** duplicate zero-terminated string */
+	int str_dup_zt(str_t *dst, const char *src);
+
+	/** duplicate zero-terminated string to zero-terminated string */
+	char *zt_strdup(const char *src);
+
+/** frees string content if allocated */
+/* void str_free_content(str_t *s); */
+#define str_free_content(str)                  \
+	do {                                       \
+		if(str != NULL) {                      \
+			if(((str)->len > 0) && ((str)->s)) \
+				cds_free((str)->s);            \
+			(str)->len = 0;                    \
+			(str)->s = 0;                      \
+		}                                      \
+	} while(0)
+
+/** frees string content if allocated and then the string itself */
+/* void str_free(str_t *s); */
+#define str_free(str)                          \
+	do {                                       \
+		if(str != NULL) {                      \
+			if(((str)->len > 0) && ((str)->s)) \
+				cds_free((str)->s);            \
+			cds_free(str);                     \
+		}                                      \
+	} while(0)
+
+/* clears string content */
+#define str_clear(str)      \
+	do {                    \
+		if(str != NULL) {   \
+			(str)->len = 0; \
+			(str)->s = 0;   \
+		}                   \
+	} while(0)
+
+
+	/** case sensitive comparation - returns 0 if equal, nonzero otherwise */
+	int str_case_equals(const str_t *a, const str_t *b);
+	/** case insensitive comparation - returns 0 if equal, nonzero otherwise */
+	int str_nocase_equals(const str_t *a, const str_t *b);
+
+	/** compare str_t and zero terminated string */
+	int str_cmp_zt(const str_t *a, const char *b); /* renamed sz_cmp */
+
+	/** is b prefix of a */
+	int str_prefix(const str_t *a, const str_t *b); /* ss_start */
+
+	/* #define ss_cmp(const str_t *a, const str_t *b) ((a->len == b->len)?sz_cmp(a, b->s):(-1)) */
+
+	/* void str_clear(str_t *s); */
+
+	/** locate character in string */
+	char *str_strchr(const str_t *s, char c);
+
+	/** locate string in string */
+	char *str_str(const str_t *s, const str_t *search_for);
+
+	/* creates new string as concatenation of a and b */
+	int str_concat(str_t *dst, str_t *a, str_t *b);
+
+	int replace_str(const str_t *src, str_t *dst, const str_t *sample,
+			const str_t *value);
+
+/** Copies string into another one. The destination string buffer
+ * MUST be allocated in needed size! */
+#define str_cpy(dst, src)                       \
+	do {                                        \
+		memcpy((dst)->s, (src)->s, (src)->len); \
+		(dst)->len = (src)->len;                \
+	} while(0)
+
+/* pointer after given string - often used when strings
+ * allocated together with data structure holding them */
+#define after_str_ptr(ss) ((ss)->s + (ss)->len)
+
+/*
+ * Append a string app with length app_len
+ * to the end of string str which is a str* pointer
+ * the buffer must be large enough
+ */
+#define str_append(str, app, app_len)                    \
+	do {                                                 \
+		memcpy((str)->s + (str)->len, (app), (app_len)); \
+		(str)->len += (app_len);                         \
+	} while(0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 46 - 0
src/lib/cds/sync.h

@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __CDS_SYNC_H
+#define __CDS_SYNC_H
+
+#ifdef SER
+#include <locking.h>
+#define cds_mutex_t gen_lock_t
+#define cds_mutex_init(m) lock_init(m)
+#define cds_mutex_destroy(m) lock_destroy(m)
+#define cds_mutex_lock(m) lock_get(m)
+#define cds_mutex_unlock(m) lock_release(m)
+#else
+#include <pthread.h>
+#include <stdlib.h>
+#define cds_mutex_t pthread_mutex_t
+#define cds_mutex_init(m) pthread_mutex_init(m, NULL)
+#define cds_mutex_destroy(m) pthread_mutex_destroy(m)
+#define cds_mutex_lock(m) pthread_mutex_lock(m)
+#define cds_mutex_unlock(m) pthread_mutex_unlock(m)
+#endif
+
+#endif

+ 127 - 0
src/lib/cds/vector.c

@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <cds/memory.h>
+#include <cds/vector.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int vector_add(vector_t *vector, void *element)
+{
+	if(vector->element_count >= vector->allocated_count) {
+		void *new_data;
+		int new_size = vector->allocated_count + vector->allocation_count;
+		if(new_size <= vector->allocated_count)
+			return -1;
+
+		new_data = (void *)cds_malloc(vector->element_size * new_size);
+		if(!new_data)
+			return -1;
+		if(vector->data) {
+			memcpy(new_data, vector->data,
+					vector->element_size * vector->allocated_count);
+			cds_free(vector->data);
+		}
+		vector->data = new_data;
+		vector->allocated_count = new_size;
+	}
+	memcpy(vector->data + (vector->element_count * vector->element_size),
+			element, vector->element_size);
+	vector->element_count++;
+
+	return 0;
+}
+
+int vector_remove(vector_t *vector, int index)
+{
+	int cnt;
+	if(index >= vector->element_count)
+		return -1;
+
+	cnt = vector->element_count - index - 1;
+	if(cnt > 0) {
+		memmove(vector->data + (index * vector->element_size),
+				vector->data + ((index + 1) * vector->element_size),
+				cnt * vector->element_size);
+	}
+	vector->element_count--;
+
+	return 0;
+}
+
+int vector_get(vector_t *vector, int index, void *element_dst)
+{
+	if(index >= vector->element_count)
+		return -1;
+
+	memcpy(element_dst, vector->data + (index * vector->element_size),
+			vector->element_size);
+
+	return 0;
+}
+
+void *vector_get_ptr(vector_t *vector, int index)
+{
+	if(index >= vector->element_count)
+		return NULL;
+	else
+		return vector->data + (index * vector->element_size);
+}
+
+void vector_destroy(vector_t *vector)
+{
+	if(vector) {
+		if(vector->data)
+			cds_free(vector->data);
+		vector->data = NULL;
+		vector->allocation_count = 0;
+		vector->element_count = 0;
+	}
+}
+
+int vector_init(vector_t *vector, int element_size, int allocation_count)
+{
+	if(!vector)
+		return -1;
+	vector->element_size = element_size;
+	vector->element_count = 0;
+	vector->allocation_count = allocation_count;
+	vector->data = (void *)cds_malloc(element_size * allocation_count);
+	if(!vector->data) {
+		vector->allocated_count = 0;
+		return -1;
+	} else {
+		vector->allocated_count = allocation_count;
+		return 0;
+	}
+}
+
+int vector_test(void)
+{
+	/*TODO: do tests for vector_t - all "methods" must be called */
+	return 0;
+}

+ 65 - 0
src/lib/cds/vector.h

@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __VECTOR_H
+#define __VECTOR_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+	/* Structure representing dynamic array of elements of
+ * equal size. */
+	typedef struct
+	{
+		int element_size;
+		/** the number of used elements */
+		int element_count;
+		/** the number of allocated elements */
+		int allocated_count;
+		/** number of elements allocated together (better than allocation
+	 * for each element separately) */
+		int allocation_count;
+		void *data;
+	} vector_t;
+
+	int vector_add(vector_t *vector, void *element);
+	int vector_get(vector_t *vector, int index, void *element_dst);
+	void *vector_get_ptr(vector_t *vector, int index);
+	int vector_remove(vector_t *vector, int index);
+	void vector_destroy(vector_t *vector);
+	int vector_init(vector_t *vector, int element_size, int allocation_count);
+
+	/** testing function - returns 0 if no errors */
+	int vector_test(void);
+
+#define vector_size(v) (v)->element_count
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif