Table of Contents
Table of Contents
Table of Contents
Common libraries are originaly determined for usage with SER - as a collection of useful functions which are not present in the SER's code. But as the time goes it seems to be good to make them usable without SER too, at least for testing parts of SER modules and thus it is possible to use them alone now.
This library depends only on standard C libraries and needs no other external libraries.
libcds (distributed with SER)
libxml2 (external library for parsing XML documents)
libcurl3 (external library for HTTP operations, used only in nonSER version!)
Table of Contents
Before installation is needed to install external libraries according to dependencies.
These libraries are distributed together with SER, but they are not compiled together with other SER code. They must be compiled separately, before compiling SER modules which use them.
There is standalone makefile for compilation with SER named
Makefile.ser.
There is an example of steps which need to be done while installing SER with these libraries into directory /base/ser/directory (if no directory specified - no prefix parameter given - default value is used: /usr/local/)
Download current ser sources:
cvs -d :pserver:anonymous@cvs.berlios.de:/cvsroot/ser checkout sip_router
Compile and install libraries for usage with SER:
cd sip_router/lib
make -f Makefile.ser install prefix=/base/ser/directory
Compile and install SER
cd ..
make install prefix=/base/ser/directory
Table of Contents
List of Examples
Table of Contents
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.
There is list of conventions used in this library:
data types (structures, enums, ...) have their names with suffix “_t” (dstring_t, str_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
Table of Contents
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.
These macros were functions and it may change in the future, but macros are probably better - they allow better debuging than functions. There are defined another macros (see cds_malloc_ptr(3), cds_free_ptr(3)), which point and will point to allocation/deallocation functions, thus they may be used as function pointers.
It is possible to redefine these macros/functions to help with memory debugging or for monitoring purposes or so.
Table of Contents
cds_malloc — memory allocation
#include <cds/memory.h>
void *cds_malloc(
|
size); |
unsigned int size;cds_free — free allocated memory
#include <cds/memory.h>
void cds_free(
|
ptr); |
void *ptr;cds_malloc_ptr — pointer to cds_malloc function independent on cds_malloc implementation (macro, ...)
#include <cds/memory.h>
void *cds_malloc_ptr(
|
size); |
unsigned int size;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 :-).
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 “SER's environment”. 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 duplictly in SER's modules.
Table of Contents
str_t — data structure for string representation
#include <cds/sstr.h>
outside of SIP Express Router:
typedef struct {
char *s;
int len;
} str_t;
inside of SIP Express Router:
typedef str str_t;
str_dup, str_dup_new, str_dup_zt — string duplication functions
#include <cds/sstr.h>
int str_dup(
|
dst, | |
src); |
str_t *dst;const str_t *src;
int str_dup_new(
|
dst, | |
src); |
str_t *dst;const char *src;
int str_dup_zt(
|
src); |
const str_t *src;All these functions allocates necessary memory using
cds_malloc.
str_dup takes as source the string given in
src
str_dup_zt takes as source zero-terminated string given in
src
str_dup_new works like str_dup
with the difference, that it allocates not only the data buffer, but the
destination str_t structure too.
str_clear — string initialization function
#include <cds/sstr.h>
void str_clear(
|
s); |
str_t *s;str_free — destroys string
#include <cds/sstr.h>
void str_free(
|
s); |
str_t *s;str_free_content — frees content of a string
#include <cds/sstr.h>
void str_free_content(
|
s); |
str_t *s;zt2str, is_str_empty, zt_strdup, str_prefix, str_strchr — various string helper functions
#include <cds/sstr.h>
str_t zt2str(
|
s); |
char *s;
int is_str_empty(
|
s); |
const str_t *s;
char *zt_strdup(
|
src); |
const char *src;
int str_prefix(
|
a, | |
b); |
const str_t *a;const str_t *b;
char *str_strchr(
|
s, | |
c); |
const str_t *s;char c;zt2str converts zero terminated string to
str_t. It doesn't copy data - both strings use the same
buffer!
is_str_empty returns 1 if given string is empty (NULL
pointer or length < 1 or NULL pointer to string data)
zt_strdup duplicates given zero terminated string to
another zero terminated string using cds_malloc function
str_prefix returns 0 if string
b is prefix of a, nonzero
otherwise (deprecated)
str_strchr searches for given character. It returns
pointer to it in the string or NULL if not found.
Dynamic string is data structure used for simple string operations hiding internal operations like memory allocations from the user.
Functions and data structures for dynamic string are declared in
dstring.h.
Table of Contents
dstring_t — data structure for dynamic string representation
#include <cds/dstring.h>
typedef struct _dstring_t {
dlink_t buffers;
int len;
int buff_size;
} dstring_t;
This structure represents dynamic string. It allows concatenation of multiple strings without worry about memory allocations.
Internaly 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 dstr_get_data(3)). Internal buffers are allocated in package memory (when compiled with SER)!
This structure is used as base for simple object serialization (see Serialization).
#include <cds/dstring.h>
#include <cds/sstr.h>
int main(int argc, char **argv)
{
dstring_t str;
str_t s;
dstr_init(&str, 256);
dstr_append_zt(&str,"This is a ");
dstr_append_zt(&str,"very long ");
dstr_append_zt(&str,"string.");
if (dstr_get_str(&str, &s) == 0) {
printf("result: %.*s\n", FMT_STR(s));
str_free_content(&s);
}
dstr_destroy(&str);
return 0;
}
This will result in
result: This is a very long
string.
dstr_init, dstr_destroy — initialization and destruction of dstring_t structure
#include <cds/dstring.h>
int dstr_init(
|
dstr, | |
buff_size); |
dstring_t *dstr;int buff_size;
int dstr_destroy(
|
dstr); |
dstring_t *dstr;dstr_init function initializes
dstring_t structure. The
value of buff_size is the size of newly allocated data
buffers. These buffers are internal and are allocated if needed by any of
dstring functions.
dstr_destroy function destroys all allocated data
buffers. After calling dstr_destroy can't be called any of
dstring manipulation functions except dstr_init.
dstr_append, dstr_append_str, dstr_append_zt — append string to dstring_t structure
#include <cds/dstring.h>
int dstr_append(
|
dstr, | |
| s, | ||
len); |
dstring_t *dstr;const char *s;int len;
int dstr_append_str(
|
dstr, | |
s); |
dstring_t *dstr;const str_t *s;
int dstr_append_zt(
|
dstr, | |
s); |
dstring_t *dstr;const char *s;All these functions are used for appending strings to dynamic string. They differ only in the string and its length specification.
dstr_append
appends data from buffer s of
length len
dstr_append_str
appends content of string s
(see str_t(3))
dstr_append_zt
appends content of zero terminated string s
dstr_get_data, dstr_get_data_length, dstr_get_data_str — exporting data from dstring_t structure
#include <cds/dstring.h>
int dstr_get_data_length(
|
dstr); |
dstring_t *dstr;
int dstr_get_data(
|
dstr, | |
dst); |
dstring_t *dstr;char *dst;
int dstr_get_data_str(
|
dstr, | |
dst); |
dstring_t *dstr;str_t *dst;dstr_get_data_length function is used to determine
the size of data present in dynamic string. It returns negative value on error.
dstr_get_data copies data from internal buffers into
given character array allocated by caller. The data size can be
determined by dstr_get_data_length call.
dstr_get_data_str copies data from internal buffers into
internally allocated string. This string is returned in the dst
parameter.
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.
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 the section called “Example”).
Table of Contents
sstream_t — input/output serialization stream
#include <cds/serialize.h>
typedef struct {
dstring_t out;
str_t in;
int in_pos;
enum { sstream_in, sstream_out } type;
} sstream_t;
This structure represents input and output serialization stream.
out
Dynamic string holding output data in the case of output stream.
in
String holding input data in the case of input stream.
in_pos
Actual position in input data (points to first unread char) in the case of input stream.
type
Member holding stream type - input or output.
Warning - internals of this data structure may change! Use it only through manipulation functions.
#include <cds/sstr.h>
#include <cds/serialize.h>
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, &t->name) != 0) return -1;
if (serialize_int(store, &t->number) != 0) return -1;
if (serialize_char(store, &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(&data);
/* storing structure to the string */
init_output_sstream(&store, 256);
if (serialize_test_struct(&store, &a) == 0) {
if (get_serialized_sstream(&store, &data) != 0)
printf("can't get data\n");
}
else printf("can't serialize\n");
destroy_sstream(&store);
/* loading structure from the string */
init_input_sstream(&store, data.s, data.len);
if (serialize_test_struct(&store, &b) == 0) {
printf("test_t = { %.*s, %d, %c }\n",
FMT_STR(b.name), b.number, b.c);
/* cleanup */
str_free_content(&b.name);
}
else printf("can't deserialize\n");
destroy_sstream(&store);
/* cleanup */
str_free_content(&data);
return 0;
}
init_input_sstream — initializes input serialization stream
#include <cds/serialize.h>
int init_input_sstream(
|
ss, | |
| data_in, | ||
data_len); |
sstream_t *ss;char *data_in;int data_len;init_output_sstream — initializes serialization stream for output
#include <cds/serialize.h>
int init_output_sstream(
|
ss, | |
out_buff_resize); |
sstream_t *ss;int out_buff_resize;get_serialized_sstream — get output stream data
#include <cds/serialize.h>
int get_serialized_sstream(
|
ss, | |
dst); |
sstream_t *ss;str_t *dst;destroy_sstream — destroys input/output serialization stream
#include <cds/serialize.h>
void destroy_sstream(
|
ss); |
sstream_t *ss;sstream_put — store data into output stream
#include <cds/serialize.h>
int sstream_put(
|
ss, | |
| s, | ||
len); |
sstream_t *ss;const char *s;int len;sstream_put_str — store data into output stream
#include <cds/serialize.h>
int sstream_put_str(
|
ss, | |
s); |
sstream_t *ss;const str_t *s;sstream_put_zt — store data into output stream
#include <cds/serialize.h>
int sstream_put_zt(
|
ss, | |
s); |
sstream_t *ss;const char *s;sstream_get — read data from input stream
#include <cds/serialize.h>
int sstream_get(
|
ss, | |
c); |
sstream_t *ss;char *c;sstream_get_str — read data from input stream
#include <cds/serialize.h>
int sstream_get_str(
|
ss, | |
| length, | ||
dst); |
sstream_t *ss;int length;str_t *dst;sstream_get_str_ex — read data from input stream
#include <cds/serialize.h>
int sstream_get_str_ex(
|
ss, | |
| len, | ||
dst); |
sstream_t *ss;int len;str_t *dst;serialize_int — integer serialization
#include <cds/serialize.h>
int serialize_int(
|
ss, | |
num); |
sstream_t *ss;int *num;serialize_uint — unsigned integer serialization
#include <cds/serialize.h>
int serialize_uint(
|
ss, | |
num); |
sstream_t *ss;unsigned int *num;serialize_char — character serialization
#include <cds/serialize.h>
int serialize_char(
|
ss, | |
c); |
sstream_t *ss;char *c;serialize_uchar — unsigned character serialization
#include <cds/serialize.h>
int serialize_uchar(
|
ss, | |
c); |
sstream_t *ss;unsigned char *c;serialize_str — string serialization
#include <cds/serialize.h>
int serialize_str(
|
ss, | |
s); |
sstream_t *ss;str_t *s;Interprocess synchronization functions and data structures are specific for SER. There are some wrapper macros for them in the CDS library.
Table of Contents
cds_mutex_t — wrapper type for mutex
#include <cds/sync.h> outside of SIP Express Router: #include <pthread.h> #define cds_mutex_t pthread_mutex_t inside of SIP Express Router: #define cds_mutex_t gen_lock_t
cds_mutex_init — mutex initialization
#include <cds/sync.h>
int cds_mutex_init(
|
m); |
cds_mutex_t *m;cds_mutex_destroy — mutex destruction
#include <cds/sync.h>
int cds_mutex_destroy(
|
m); |
cds_mutex_t *m;cds_mutex_lock — mutex lock
#include <cds/sync.h>
int cds_mutex_lock(
|
m); |
cds_mutex_t *m;Message queue is implementation of simple FIFO. It is declared in
msg_queue.h.
Table of Contents
msg_queue_t — message queue data structure
#include <cds/msg_queue.h>
typedef struct msg_queue {
mq_message_t *first;
mq_message_t *last;
cds_mutex_t q_mutex;
int use_mutex;
} msg_queue_t;
mq_message_t — message data structure
#include <cds/msg_queue.h>
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;
Data structure used as basic element in message queue. Pointer to
message data should be obtained by get_message_data.
There are more possibilities how to allocate message data:
explicitly, data buffer is allocated outside of mq_message_t structure and only pointer to it is stored in this structure, see create_message(3)
implicitly, data buffer is allocated together with mq_message_t structure - data must be copied into it after structure allocation, see create_message_ex(3)
there is third possibility, that data and message - both -
are allocated by caller without using
create_message, create_message_ex and
msg_free, see init_message_ex(3)
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.
Warning: internal implementation of this structure may change, use it only through existing functions.
msg_queue_init — message queue initialization
#include <cds/msg_queue.h>
int msg_queue_init(
|
q); |
msg_queue_t *q;msg_queue_init_ex — message queue initialization
#include <cds/msg_queue.h>
int msg_queue_init_ex(
|
q, | |
synchronized); |
msg_queue_t *q;int synchronized;msg_queue_destroy — destroy message queue
#include <cds/msg_queue.h>
void msg_queue_destroy(
|
q); |
msg_queue_t *q;push_message — push message into message queue
#include <cds/msg_queue.h>
int push_message(
|
q, | |
msg); |
msg_queue_t *q;mq_message_t *msg;Function pushes initialized message into message queue. This
message may be removed from the queue using pop_message.
Unremoved messages are automaticaly freed by msg_queue_destroy
(depending on message initialization, see create_message(3), create_message_ex(3) and init_message_ex(3)).
pop_message — pop message from the queue
#include <cds/msg_queue.h>
mq_message_t *pop_message(
|
q); |
msg_queue_t *q;Removes first message from the queue. If the queue is empty or an error
occured it returns NULL value. Removed messages are NOT automaticaly freed -
caller must use free_message or free it itself (see free_message(3))!
is_msg_queue_empty — test if message queue empty
#include <cds/msg_queue.h>
int is_msg_queue_empty(
|
q); |
msg_queue_t *q;create_message — allocates and initializes message
#include <cds/msg_queue.h>
int create_message(
|
data, | |
data_len); |
void *data;int data_len;Allocates message using cds_malloc and initializes
its content so it will be freed automaticaly. Pointer to the explicitly
allocated data is set to data and its length is set to
data_len. Message created by create_message
should be freed using message_free.
Unremoved messages created this way are freed automaticaly in
msg_queue_destroy using free_message.
Calling free_message to such message frees the
message and the data given by parameter data too, thus
they can NOT be freed by the caller!
create_message_ex — create and initialize message
#include <cds/msg_queue.h>
mq_message_t *create_message_ex(
|
data_len); |
int data_len;Allocates message with data of given size
(data_len) using cds_malloc. It
initializes message content so it will be freed automaticaly.
Pointer to allocated data should be obtained by
get_message_data.
Messages created by create_message_ex
should be freed using message_free.
Unremoved messages created this way are freed automaticaly in
msg_queue_destroy using free_message.
init_message_ex — initialize message
#include <cds/msg_queue.h>
void init_message_ex(
|
m, | |
| data, | ||
| data_len, | ||
func); |
mq_message_t *m;void *data;int data_len;destroy_function_f func;Initializes message structure with given data and given data length like
create_message but without its allocation.
Parameter func specifies function called on data pointer
before freeing the message in free_message. It can be NULL.
This function may be used for example for memory deallocation (for example may
have value of cds_free_ptr) or some more complicated
function for freeing complex data structure with pointers inside or so.
set_data_destroy_function — set function used to deallocate message data
#include <cds/msg_queue.h> typedef void (*destroy_function_f)(void *);
void set_data_destroy_function(
|
msg, | |
func); |
mq_message_t *msg;destroy_function_f func;Set destroy function for message data. This function is called from
free_message and is primarily used for deallocation of
complex data structures or their content. It can be used on all types of
messages (allocated using create_message or
create_message_ex or initialized using
init_message_ex).
Example 1. Usage with create_message_ex
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");
Example 2. Usage with create_message
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");
free_message — free message
#include <cds/msg_queue.h>
void free_message(
|
msg); |
mq_message_t *msg;Frees message. If data is allocated explicitly it frees it using
cds_free,
if they are allocated implicitly, it is freed together with message. Thus simple
data strutures are deallocated automaticaly 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
set_data_destroy_function.
Table of Contents
Table of Contents
This library contains functions for manipulating data using XCAP protocol.
Table of Contents
Table of Contents
This library contains data structures for presence documents representation and helper functions.