Browse code

Merge branch 'tteras/mohqueue'

Timo Teräs authored on 07/10/2013 08:18:02
Showing 17 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,14 @@
0
+<?xml version="1.0" encoding="UTF-8"?>
1
+<!DOCTYPE database PUBLIC "-//kamailio.org//DTD DBSchema V1.1//EN"
2
+  "http://kamailio.org/pub/kamailio/dbschema/dtd/1.1/dbschema.dtd" [
3
+
4
+<!ENTITY % entities SYSTEM "entities.xml">
5
+%entities;
6
+
7
+]>
8
+
9
+<database xmlns:xi="http://www.w3.org/2001/XInclude">
10
+    <name>mohqueue</name>
11
+    <xi:include href="mohqcalls.xml"/>
12
+    <xi:include href="mohqueues.xml"/>
13
+</database>
0 14
new file mode 100644
... ...
@@ -0,0 +1,76 @@
0
+<?xml version="1.0" encoding="UTF-8"?>
1
+<!DOCTYPE table PUBLIC "-//kamailio.org//DTD DBSchema V1.1//EN" 
2
+  "http://kamailio.org/pub/kamailio/dbschema/dtd/1.1/dbschema.dtd" [
3
+
4
+<!ENTITY % entities SYSTEM "entities.xml">
5
+%entities;
6
+
7
+]>
8
+
9
+<table id="mohqcalls" xmlns:db="http://docbook.org/ns/docbook">
10
+  <name>mohqcalls</name>
11
+  <version>1</version>
12
+  <type db="mysql">&MYSQL_TABLE_TYPE;</type>
13
+  <description>
14
+    <db:para>This table is used by the mohqueue module to store call information. This is a read-only table from the viewpoint of outside processes. More information about the mohqueue module can be found at: &KAMAILIO_MOD_DOC;mohqueue.html
15
+    </db:para>
16
+  </description>
17
+
18
+  <column id="id">
19
+    <name>id</name>
20
+    <type>unsigned int</type>
21
+    <size>&table_id_len;</size>
22
+    <autoincrement/>
23
+    <primary/>
24
+    <type db="dbtext">int,auto</type>
25
+    <description>Unique ID</description>
26
+  </column>
27
+
28
+  <column id="mohq_id">
29
+    <name>mohq_id</name>
30
+    <type>unsigned int</type>
31
+    <size>&table_id_len;</size>
32
+    <description>queue id</description>
33
+  </column>
34
+
35
+  <column id="call_id">
36
+    <name>call_id</name>
37
+    <type>string</type>
38
+    <size>100</size>
39
+    <description>Call-ID header</description>
40
+  </column>
41
+
42
+  <column id="call_status">
43
+    <name>call_status</name>
44
+    <type>unsigned int</type>
45
+    <description>status of call</description>
46
+  </column>
47
+
48
+  <column id="call_from">
49
+    <name>call_from</name>
50
+    <type>string</type>
51
+    <size>100</size>
52
+    <description>From header</description>
53
+  </column>
54
+
55
+  <column id="call_contact">
56
+    <name>call_contact</name>
57
+    <type>string</type>
58
+    <size>100</size>
59
+    <null/>
60
+    <description>Contact header</description>
61
+  </column>
62
+
63
+  <column id="call_time">
64
+    <name>call_time</name>
65
+    <type>datetime</type>
66
+    <default db="oracle">to_date('','yyyy-mm-dd hh24:mi:ss')</default>
67
+    <description>time when call first entered queue</description>
68
+  </column>
69
+
70
+  <index>
71
+    <name>mohqcalls_idx</name>
72
+    <colref linkend="call_id" />
73
+    <unique/>
74
+  </index>
75
+</table>
0 76
new file mode 100644
... ...
@@ -0,0 +1,75 @@
0
+<?xml version="1.0" encoding="UTF-8"?>
1
+<!DOCTYPE table PUBLIC "-//kamailio.org//DTD DBSchema V1.1//EN" 
2
+  "http://kamailio.org/pub/kamailio/dbschema/dtd/1.1/dbschema.dtd" [
3
+
4
+<!ENTITY % entities SYSTEM "entities.xml">
5
+%entities;
6
+
7
+]>
8
+
9
+<table id="mohqueues" xmlns:db="http://docbook.org/ns/docbook">
10
+  <name>mohqueues</name>
11
+  <version>1</version>
12
+  <type db="mysql">&MYSQL_TABLE_TYPE;</type>
13
+  <description>
14
+    <db:para>This table is used by the mohqueue module to store queue definitions. This is a read-only table from the viewpoint of the module. More information about the mohqueue module can be found at: &KAMAILIO_MOD_DOC;mohqueue.html
15
+    </db:para>
16
+  </description>
17
+
18
+  <column id="id">
19
+    <name>id</name>
20
+    <type>unsigned int</type>
21
+    <size>&table_id_len;</size>
22
+    <autoincrement/>
23
+    <primary/>
24
+    <type db="dbtext">int,auto</type>
25
+    <description>Unique ID</description>
26
+  </column>
27
+
28
+  <column id="name">
29
+    <name>name</name>
30
+    <type>string</type>
31
+    <size>25</size>
32
+    <description>queue name</description>
33
+  </column>
34
+
35
+  <column id="uri">
36
+    <name>uri</name>
37
+    <type>string</type>
38
+    <size>100</size>
39
+    <description>URI for the queue</description>
40
+  </column>
41
+
42
+  <column id="mohdir">
43
+    <name>mohdir</name>
44
+    <type>string</type>
45
+    <size>100</size>
46
+    <null/>
47
+    <description>directory for MOH files</description>
48
+  </column>
49
+
50
+  <column id="mohfile">
51
+    <name>mohfile</name>
52
+    <type>string</type>
53
+    <size>100</size>
54
+    <description>base name for the MOH file</description>
55
+  </column>
56
+
57
+  <column id="debug">
58
+    <name>debug</name>
59
+    <type>int</type>
60
+    <description>debug flag</description>
61
+  </column>
62
+
63
+  <index>
64
+    <name>mohqueue_uri_idx</name>
65
+    <colref linkend="uri" />
66
+    <unique/>
67
+  </index>
68
+
69
+  <index>
70
+    <name>mohqueue_name_idx</name>
71
+    <colref linkend="name" />
72
+    <unique/>
73
+  </index>
74
+</table>
0 75
new file mode 100644
... ...
@@ -0,0 +1,18 @@
0
+# $Id$
1
+#
2
+# msgqueue module makefile
3
+#
4
+# 
5
+# WARNING: do not run this directly, it should be run by the master Makefile
6
+
7
+include ../../Makefile.defs
8
+auto_gen=
9
+NAME=mohqueue.so
10
+LIBS=
11
+
12
+DEFS+=-DKAMAILIO_MOD_INTERFACE
13
+
14
+SERLIBPATH=../../lib
15
+SER_LIBS+=$(SERLIBPATH)/kcore/kcore $(SERLIBPATH)/srdb1/srdb1
16
+SER_LIBS+=$(SERLIBPATH)/kmi/kmi
17
+include ../../Makefile.modules
0 18
new file mode 100644
... ...
@@ -0,0 +1,11 @@
0
+Things to look into:
1
+
2
+* RFC3261, section 12.1.1 requires UAS to copy Record-Route
3
+
4
+* Check to see if any memory leaks.
5
+
6
+* Should probably respond when caller says BYE after queue says BYE.
7
+
8
+* check RAck number
9
+
10
+* check Require header for unsupported values
0 11
\ No newline at end of file
1 12
new file mode 100644
... ...
@@ -0,0 +1,4 @@
0
+docs = mohqueue.xml
1
+
2
+docbook_dir = ../../../docbook
3
+include $(docbook_dir)/Makefile.module
0 4
new file mode 100644
... ...
@@ -0,0 +1,31 @@
0
+<?xml version="1.0" encoding="UTF-8"?>
1
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
2
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
3
+
4
+<!-- general documentation entities -->
5
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
6
+%docentities;
7
+
8
+]>
9
+
10
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
11
+  <bookinfo>
12
+    <title>mohqueue Module</title>
13
+    <productname class="trade">&kamailioname;</productname>
14
+    <authorgroup>
15
+      <author>
16
+        <firstname>Robert</firstname>
17
+        <surname>Boisvert</surname>
18
+        <address>
19
+          <email>rdbprog@gmail.com</email>
20
+        </address>
21
+      </author>
22
+    </authorgroup>
23
+    <copyright>
24
+      <year>2013</year>
25
+      <holder>Robert Boisvert, rdbprog@gmail.com</holder>
26
+    </copyright>
27
+  </bookinfo>
28
+  <toc></toc>
29
+  <xi:include href="mohqueue_admin.xml" />
30
+</book>
0 31
\ No newline at end of file
1 32
new file mode 100644
... ...
@@ -0,0 +1,510 @@
0
+<?xml version="1.0" encoding='ISO-8859-1'?>
1
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
2
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
3
+
4
+<!-- Include general documentation entities -->
5
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
6
+%docentities;
7
+
8
+]>
9
+<!-- Module Admin Guide -->
10
+
11
+<chapter xmlns:xi="http://www.w3.org/2001/XInclude">
12
+  <title>&adminguide;</title>
13
+
14
+  <section id="overview">
15
+    <title>Overview</title>
16
+    <para>
17
+The mohqueue module diverts INVITE requests into a
18
+<ulink url="http://en.wikipedia.org/wiki/Music_on_hold">Music On
19
+Hold (MOH)</ulink> queue where the caller can listen to recorded
20
+audio until an operator is available to take the call. When an
21
+operator is available, a function can be used to transfer the oldest
22
+call in a queue to an operator using an unattended transfer (REFER)
23
+to a specified URI. If successful, the call is removed from the queue.
24
+    </para>
25
+    <para>
26
+While in queue, recorded audio is streamed to the caller in an endless
27
+loop using the rtpproxy module and application. Each queue can be
28
+configured to use different audio files.
29
+    </para>
30
+    <para>
31
+The queues are defined in the database which allows for dynamic
32
+configuration of the queues. Each queue is assigned a specific
33
+URI to respond to and a location for the audio files.
34
+    </para>
35
+    <para>
36
+As each call arrives the database is updated to show the call
37
+status which allows outside processes to inspect the queue. It
38
+can also be inspected using a function to see how many calls are
39
+currently in queue.
40
+    </para>
41
+    <para>
42
+While in queue, all SIP messages for a call must pass through
43
+the mohqueue module so that it can accurately detect the call
44
+status.
45
+    </para>
46
+  </section>
47
+
48
+  <section id="dependencies">
49
+    <title>Dependencies</title>
50
+
51
+    <section id="mod.depends">
52
+      <title>Kamailio Modules</title>
53
+      <para>
54
+The following modules must be loaded before this module:
55
+        <itemizedlist>
56
+          <listitem><emphasis>a database module</emphasis></listitem>
57
+          <listitem><emphasis>sl module</emphasis></listitem>
58
+          <listitem><emphasis>tm module</emphasis></listitem>
59
+          <listitem><emphasis>rtpproxy module</emphasis></listitem>
60
+        </itemizedlist>
61
+      </para>
62
+    </section>
63
+
64
+    <section id="app.depends">
65
+      <title>External Libraries or Applications</title>
66
+      <para>
67
+The rtpproxy applications supported by the rtpproxy module (e.g.
68
+<ulink url="http://www.b2bua.org/wiki/RTPproxy">
69
+http://www.b2bua.org/wiki/RTPproxy</ulink>).
70
+      </para>
71
+    </section>
72
+
73
+  </section>
74
+
75
+  <section id="parameters">
76
+    <title>Parameters</title>
77
+
78
+    <section id="url.parms">
79
+      <title><varname>db_url</varname> (str)</title>
80
+      <para>
81
+The URL to connect to the database for the mohqueue tables.
82
+      </para>
83
+      <para>
84
+<emphasis>Default value for Kamailio.</emphasis>
85
+      </para>
86
+      <example>
87
+        <title>Set <varname>db_url</varname>:</title>
88
+        <programlisting format="linespecific">
89
+...
90
+modparam ("mohqueue", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
91
+...
92
+        </programlisting>
93
+      </example>
94
+    </section>
95
+
96
+    <section id="table.parms">
97
+      <title><varname>db_qtable</varname> and <varname>db_ctable</varname> (str)</title>
98
+      <para>
99
+<varname>db_qtable</varname> is the name of the table that defines
100
+the queues and <varname>db_ctable</varname> is the table that
101
+maintains the call status.
102
+      </para>
103
+      <para>
104
+<emphasis>"MOHQUEUES" for <varname>db_qtable</varname> and
105
+"MOHQCALLS" for <varname>db_ctable</varname>.</emphasis>
106
+      </para>
107
+      <example>
108
+        <title>Set table names:</title>
109
+        <programlisting format="linespecific">
110
+...
111
+modparam ("mohqueue", "db_qtable", "mqueues")
112
+modparam ("mohqueue", "db_ctable", "mcalls")
113
+...
114
+        </programlisting>
115
+      </example>
116
+    </section>
117
+
118
+    <section id="dir.parms">
119
+      <title><varname>mohdir</varname> (str)</title>
120
+      <para>
121
+Path to the directory where the audio files are stored. Audio files
122
+are usually relative to this directory although the value can be
123
+overridden by a directory specified in the queues table.
124
+      </para>
125
+      <para>
126
+<emphasis>None. If not set by the module it must be defined in the
127
+queues table.</emphasis>
128
+      </para>
129
+      <example>
130
+        <title>Set default directory for audio files:</title>
131
+        <programlisting format="linespecific">
132
+...
133
+modparam ("mohqueue", "mohdir", "/var/kamailio/MOH")
134
+...
135
+        </programlisting>
136
+      </example>
137
+    </section>
138
+
139
+    <section id="maxcalls.parms">
140
+      <title><varname>moh_maxcalls</varname> (integer)</title>
141
+      <para>
142
+Defines the maximum number of calls that can be placed in queue.
143
+It is the sum of all calls in all queues. It must be in the range
144
+of 1 to 5000. <emphasis>NOTE:</emphasis> it may be limited by the
145
+processing power of the server or the number of available rtpproxy
146
+ports.
147
+      </para>
148
+      <para>
149
+<emphasis>None. If not set by the module it must be defined in the
150
+queues table.</emphasis>
151
+      </para>
152
+      <example>
153
+        <title>Set default directory for audio files:</title>
154
+        <programlisting format="linespecific">
155
+...
156
+modparam ("mohqueue", "mohdir", "/var/kamailio/MOH")
157
+...
158
+        </programlisting>
159
+      </example>
160
+    </section>
161
+
162
+  </section>
163
+
164
+  <section id="functions">
165
+    <title>Functions</title>
166
+
167
+    <section id="proc.func">
168
+      <title>
169
+        <function moreinfo="none">mohq_process ()</function>
170
+      </title>
171
+      <para>
172
+Checks to see if the current SIP message involves a queue. If it
173
+does it will process the message and return a TRUE value.
174
+      </para>
175
+      <para>
176
+In order for mohqueue to detect changes in the call it is necessary
177
+that all messages involving the call be processed through this
178
+function. The easiest way is to accomplish this is to place it at
179
+the beginning of the main route of the script.
180
+      </para>
181
+      <para>
182
+mohqueue calls are identified by an RURI that matches a queue URI.
183
+Once a call is placed in queue it checks the <varname>To</varname>
184
+header field along with the RURI to find a match, except in the case
185
+of a CANCEL which matches only on the RURI.
186
+      </para>
187
+      <para>
188
+This function has no parameters and must be called from a request route.
189
+      </para>
190
+      <para>
191
+<emphasis>Return code:</emphasis>
192
+        <itemizedlist>
193
+          <listitem>
194
+            <emphasis>TRUE=successful and call in queue</emphasis>
195
+          </listitem>
196
+          <listitem>
197
+            <emphasis>FALSE=failed, unrecognized URI or unable to place in queue</emphasis>
198
+          </listitem>
199
+        </itemizedlist>
200
+      </para>
201
+      <example>
202
+        <title><function>mohq_process</function> usage:</title>
203
+        <programlisting format="linespecific">
204
+...
205
+request_route {
206
+  # main route with limited processing
207
+...
208
+  # MOH queue?
209
+  if (mohq_process ()) {
210
+    xlog ("L_DBG", "Handled by mohqueue");
211
+    exit;
212
+  }
213
+  # An error or not a MOH queue message; continue processing
214
+...
215
+}
216
+...
217
+        </programlisting>
218
+      </example>
219
+    </section>
220
+
221
+    <section id="send.func">
222
+      <title>
223
+        <function moreinfo="none">mohq_send (queue_name)</function>
224
+      </title>
225
+      <para>
226
+Normally calls enter the queue with an initial INVITE message that
227
+1) has a RURI that matches a queue URI and 2) is passed through
228
+<function>mohq_proc ()</function>, which is the preferred method.
229
+      </para>
230
+      <para>
231
+This function is used when you wish to send a call into a queue that
232
+does not match the queue URI.
233
+      </para>
234
+      <para>
235
+It has only one parameter, the name of the queue, and must be called
236
+from the request route with an initial INVITE message. The queue name
237
+can be passed as a literal or pseudo-variable.
238
+      </para>
239
+      <para>
240
+<emphasis>Return code:</emphasis>
241
+        <itemizedlist>
242
+          <listitem>
243
+            <emphasis>TRUE=successful and call in queue</emphasis>
244
+          </listitem>
245
+          <listitem>
246
+            <emphasis>FALSE=failed, unable to place in queue</emphasis>
247
+          </listitem>
248
+        </itemizedlist>
249
+      </para>
250
+      <example>
251
+        <title><function>mohq_send</function> usage:</title>
252
+        <programlisting format="linespecific">
253
+...
254
+  # call is initial INVITE and ready for queue?
255
+  if (some test) {
256
+    if (mohq_send ("main")) {
257
+      xlog ("L_DBG", "Sent call to main mohqueue");
258
+      exit;
259
+    }
260
+    # failed to enter queue!
261
+    ...
262
+  }
263
+...
264
+        </programlisting>
265
+      </example>
266
+    </section>
267
+
268
+    <section id="retrieve.func">
269
+      <title>
270
+        <function moreinfo="none">mohq_retrieve (queue_name, URI)</function>
271
+      </title>
272
+      <para>
273
+Retrieves the oldest call in a queue and redirects it to a URI.
274
+Although the function returns, the transfer of the call may not have
275
+completed since the new URI (operator) must answer the call.
276
+      </para>
277
+      <para>
278
+It has two parameters, the queue name and the URI to REFER the call
279
+to, both which can be passed as literals or pseudo-variables. It can
280
+be called from any route.
281
+      </para>
282
+      <para>
283
+<emphasis>Return code:</emphasis>
284
+        <itemizedlist>
285
+          <listitem>
286
+            <emphasis>TRUE=successful, transfer started</emphasis>
287
+          </listitem>
288
+          <listitem>
289
+            <emphasis>FALSE=failed, parameters are incorrect or there are no calls in queue</emphasis>
290
+          </listitem>
291
+        </itemizedlist>
292
+      </para>
293
+      <example>
294
+        <title><function>mohq_retrieve</function> usage:</title>
295
+        <programlisting format="linespecific">
296
+...
297
+#!define MOHQNAME "operators"
298
+#!define CGROUP   "sip:operators@10.211.64.5"
299
+...
300
+  # redirect oldest call to operator call group
301
+  if (mohq_retrieve (MOHQNAME, CGROUP)) {
302
+      xlog ("L_DBG", "Retrieved call from mohqueue");
303
+      exit;
304
+    }
305
+  # queue is empty or something went wrong
306
+  }
307
+...
308
+        </programlisting>
309
+      </example>
310
+    </section>
311
+
312
+    <section id="count.func">
313
+      <title>
314
+        <function moreinfo="none">mohq_count (queue_name, pvar)</function>
315
+      </title>
316
+      <para>
317
+Finds the number of calls that are in a queue. It will not count
318
+calls that are in the process of entering or exiting the queue.
319
+      </para>
320
+      <para>
321
+The function has two parameters, the name of the queue and the
322
+pseudo-variable which receives the count. The queue name can be
323
+passed as a literal or a pseudo-variable. It can be called from
324
+any route.
325
+      </para>
326
+      <para>
327
+<emphasis>Return code:</emphasis>
328
+        <itemizedlist>
329
+          <listitem>
330
+            <emphasis>TRUE=successful, pseudo-variable contains count</emphasis>
331
+          </listitem>
332
+          <listitem>
333
+            <emphasis>FALSE=failed, parameters are incorrect</emphasis>
334
+          </listitem>
335
+        </itemizedlist>
336
+      </para>
337
+      <example>
338
+        <title><function>mohq_count</function> usage:</title>
339
+        <programlisting format="linespecific">
340
+...
341
+$var(mohq) = "operators";
342
+...
343
+  # more than 10 calls?
344
+  mohq_count ("$var(mohq)", "$var(mohqcnt)");
345
+  if ($var(mohqcnt) > 10) {
346
+    xlog ("L_WARN", "$var(mohq) queue has $var(mohqcnt) calls!");
347
+  }
348
+...
349
+        </programlisting>
350
+      </example>
351
+    </section>
352
+
353
+  </section>
354
+
355
+  <section id="database">
356
+    <title>Database Schema</title>
357
+      <para>
358
+mohqueue uses two external database tables to manage the queues and
359
+provide status information to outside processes. Internally, it keeps
360
+a volatile database in memory of call status. If the module is
361
+restarted it loses the internal database and clears the external
362
+one.
363
+      </para>
364
+      <para>
365
+On a reqular basis it checks the external table that defines the
366
+queues to see if the definition has changed. It makes this check
367
+under the following conditions: the queue has not been checked in the
368
+last 60 seconds <emphasis>AND</emphasis> no call is currently in
369
+queue or transitioning in or out. The last condition prevents
370
+existing calls from being adversely affected by queue redefinitions.
371
+      </para>
372
+
373
+    <section id="mohqueues.dbase">
374
+      <title>MOHQUEUES Table</title>
375
+      <para>
376
+This table controls the definition of the queue. The name is set by
377
+the <ulink url="#table.parms">db_qtable</ulink> parameter. There is
378
+no internal function to modify the table so it must be configured
379
+externally. It contains the following fields:
380
+        <itemizedlist>
381
+          <listitem>
382
+<emphasis>id</emphasis> (integer): unique identifier that is created
383
+automatically. <emphasis>Do not attempt to change this value.</emphasis>
384
+          </listitem>
385
+          <listitem>
386
+<emphasis>name</emphasis> (25-character string, required): the queue name.
387
+Duplicate names are not allowed.
388
+          </listitem>
389
+          <listitem>
390
+<emphasis>uri</emphasis> (100-character string, required): the URI of
391
+the queue. It should not include any parameters or headers (e.g.
392
+"sip:user@host;maddr=239.255.255.1" or "sip:user@host?subject=project")
393
+although it will match any RURI that contains this URI even if the
394
+RURI has parameters or headers. Duplicates are not allowed.
395
+          </listitem>
396
+          <listitem>
397
+<emphasis>mohdir</emphasis> (100-character string, optional): path to
398
+the directory where the audio files for the queue are stored. This path
399
+overrides the one provided by the <ulink url="#dir.parms">mohdir</ulink>
400
+parameter. If the directory is not accessible by the module the queue
401
+is not activated.
402
+          </listitem>
403
+          <listitem>
404
+<emphasis>mohfile</emphasis> (100-character string, required): the
405
+base name of the audio file. See the section about
406
+<ulink url="#audiofiles">audio files</ulink> for more information
407
+about file names. If no files matching this name are found in the
408
+directory the queue is not activated.
409
+          </listitem>
410
+          <listitem>
411
+<emphasis>debug</emphasis> (integer, required): enables debugging
412
+messages for the queue. If non-zero, it will send debugging messages
413
+to the log for conditions that involve the queue, whether or not
414
+Kamailio has logging enabled for debugging. If zero, it depends on
415
+Kamailio's log level.
416
+          </listitem>
417
+        </itemizedlist>
418
+      </para>
419
+    </section>
420
+
421
+    <section id="mohqcalls.dbase">
422
+      <title>MOHQCALLS Table</title>
423
+      <para>
424
+This table contains the status of calls that are in queue, or
425
+transitioning in or out of a queue. The name is set by the
426
+<ulink url="#table.parms">db_ctable</ulink> parameter. This table
427
+is read-only for external processes and its contents should
428
+<emphasis>not be modified</emphasis>. It contains the following
429
+fields:
430
+        <itemizedlist>
431
+          <listitem>
432
+<emphasis>id</emphasis> (integer): unique identifier that is created
433
+automatically.
434
+          </listitem>
435
+          <listitem>
436
+<emphasis>mohq_id</emphasis> (integer, required): the id value of the
437
+queue.
438
+          </listitem>
439
+          <listitem>
440
+<emphasis>call_status</emphasis> (integer, required): the status of
441
+the call. 1=entering; 2=in queue (listening to MOH); 3=leaving
442
+          </listitem>
443
+          <listitem>
444
+<emphasis>call_from</emphasis> (100-character string, required): the
445
+contents of the <varname>From</varname> header field.
446
+          </listitem>
447
+          <listitem>
448
+<emphasis>call_id</emphasis> (100-character string, required): the
449
+contents of the <varname>Call-ID</varname> header field.
450
+          </listitem>
451
+          <listitem>
452
+<emphasis>call_contact</emphasis> (100-character string, optional):
453
+the contents of the <varname>Contact</varname> header field, if it
454
+exists.
455
+          </listitem>
456
+          <listitem>
457
+<emphasis>call_time</emphasis> (datetime, required): time the call
458
+entered the queue. If a <ulink url="#retrieve.func">retrieve</ulink>
459
+fails this time is not changed.
460
+          </listitem>
461
+        </itemizedlist>
462
+      </para>
463
+    </section>
464
+
465
+  </section>
466
+  <section id="audiofiles">
467
+    <title>Audio Files</title>
468
+      <para>
469
+When rtpproxy negotiates to determine which media to use in the audio
470
+stream it uses the files in the MOH directory as defined by the
471
+<ulink url="#mohqueues.dbase">MOHQUEUES</ulink> table. The table
472
+defines the location of the files and the base name used to identify
473
+each. The actual stream type depends on the RTP payload number that
474
+is part of the name. The complete file name for each stream is
475
+composed of <varname>mohdir/mohfile.type</varname>. For example,
476
+<varname>/var/kamailio/MOH/HeWillCall.8</varname> would be the file
477
+for payload type 8 (PCMA/8000).
478
+      </para>
479
+      <para>
480
+The supported types and their order of preference are:
481
+        <itemizedlist>
482
+          <listitem><emphasis>9</emphasis>: G722/8000</listitem>
483
+          <listitem><emphasis>0</emphasis>: PCMU/8000</listitem>
484
+          <listitem><emphasis>8</emphasis>: PCMA/8000</listitem>
485
+          <listitem><emphasis>18</emphasis>: G729/8000</listitem>
486
+          <listitem><emphasis>3</emphasis>: GSM/8000</listitem>
487
+          <listitem><emphasis>4</emphasis>: G723/8000</listitem>
488
+          <listitem><emphasis>15</emphasis>: G728/8000</listitem>
489
+          <listitem><emphasis>5</emphasis>: DVI4/8000</listitem>
490
+          <listitem><emphasis>7</emphasis>: LPC/8000</listitem>
491
+          <listitem><emphasis>12</emphasis>: QCELP/8000</listitem>
492
+          <listitem><emphasis>13</emphasis>: CN/8000</listitem>
493
+          <listitem><emphasis>16</emphasis>: DVI4/11025</listitem>
494
+          <listitem><emphasis>6</emphasis>: DVI4/16000</listitem>
495
+          <listitem><emphasis>17</emphasis>: DVI4/22050</listitem>
496
+          <listitem><emphasis>10</emphasis>: L16/44100</listitem>
497
+          <listitem><emphasis>11</emphasis>: L16/44100</listitem>
498
+          <listitem><emphasis>14</emphasis>: MPA/90000</listitem>
499
+        </itemizedlist>
500
+      </para>
501
+      <para>
502
+See <ulink url="http://en.wikipedia.org/wiki/RTP_audio_video_profile">
503
+RTP Audio Video Profile</ulink> for more information about RTP
504
+payload types.
505
+      </para>
506
+
507
+  </section>
508
+
509
+</chapter>
0 510
new file mode 100644
... ...
@@ -0,0 +1,442 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2013 Robert Boisvert
4
+ *
5
+ * This file is part of the mohqueue module for sip-router, a free SIP server.
6
+ *
7
+ * The mohqueue module is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * The mohqueue module is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
+ *
21
+ */
22
+
23
+#include <sys/types.h>
24
+#include <stdlib.h>
25
+
26
+#include "mohq.h"
27
+#include "mohq_db.h"
28
+#include "mohq_funcs.h"
29
+
30
+MODULE_VERSION
31
+
32
+/**********
33
+* local function declarations
34
+**********/
35
+
36
+int fixup_count (void **, int);
37
+static int mod_child_init (int);
38
+static void mod_destroy (void);
39
+static int mod_init (void);
40
+
41
+/**********
42
+* global varbs
43
+**********/
44
+
45
+mod_data *pmod_data;
46
+
47
+/**********
48
+* module exports
49
+**********/
50
+
51
+/* COMMANDS */
52
+static cmd_export_t mod_cmds [] = {
53
+  { "mohq_count", (cmd_function) mohq_count, 2, fixup_count, 0,
54
+    REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
55
+  { "mohq_process", (cmd_function) mohq_process, 0, NULL, 0, REQUEST_ROUTE },
56
+  { "mohq_retrieve", (cmd_function) mohq_retrieve, 2, fixup_spve_spve, 0,
57
+    REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
58
+  { "mohq_send", (cmd_function) mohq_send, 1, fixup_spve_spve, 0, REQUEST_ROUTE },
59
+  { NULL, NULL, -1, 0, 0 },
60
+};
61
+
62
+/* PARAMETERS */
63
+char *db_url = DEFAULT_DB_URL;
64
+char *db_ctable = "mohqcalls";
65
+char *db_qtable = "mohqueues";
66
+char *mohdir = "";
67
+int moh_maxcalls = 50;
68
+
69
+static param_export_t mod_parms [] = {
70
+  { "db_url", STR_PARAM, &db_url },
71
+  { "db_ctable", STR_PARAM, &db_ctable },
72
+  { "db_ctable", STR_PARAM, &db_qtable },
73
+  { "mohdir", STR_PARAM, &mohdir },
74
+  { "moh_maxcalls", INT_PARAM, &moh_maxcalls },
75
+  { NULL, 0, NULL },
76
+};
77
+
78
+/* MI COMMANDS */
79
+static mi_export_t mi_cmds [] = {
80
+  { "debug", mi_debug, 0, 0, 0 },
81
+  { "drop_call", mi_drop_call, 0, 0, 0 },
82
+  { 0, 0, 0, 0, 0 }
83
+};
84
+
85
+/* MODULE EXPORTS */
86
+struct module_exports exports = {
87
+  "mohqueue",       /* module name */
88
+  DEFAULT_DLFLAGS,  /* dlopen flags */
89
+  mod_cmds,         /* exported functions */
90
+  mod_parms,        /* exported parameters */
91
+  0,                /* statistics */
92
+  mi_cmds,          /* MI functions */
93
+  0,                /* exported pseudo-variables */
94
+  0,                /* extra processes */
95
+  mod_init,         /* module initialization function */
96
+  0,                /* response handling function */
97
+  mod_destroy,      /* destructor function */
98
+  mod_child_init,   /* per-child initialization function */
99
+};
100
+
101
+/**********
102
+* local functions
103
+**********/
104
+
105
+/**********
106
+* Fixup Count
107
+*
108
+* INPUT:
109
+*   Arg (1) = parameter array pointer
110
+*   Arg (1) = parameter number
111
+* OUTPUT: -1 if failed; 0 if saved as pv_elem_t
112
+**********/
113
+
114
+int fixup_count (void **param, int param_no)
115
+
116
+{
117
+if (param_no == 1)
118
+  { return fixup_spve_spve (param, 1); }
119
+if (param_no == 2)
120
+  { return fixup_pvar_null (param, 1); }
121
+return 0;
122
+}
123
+
124
+/**********
125
+* Configuration Initialization
126
+*
127
+* INPUT:
128
+*   pmod_data memory allocated
129
+*   configuration values set
130
+* OUTPUT: 0 if failed; else pmod_data has config values
131
+**********/
132
+
133
+static int init_cfg (void)
134
+
135
+{
136
+/**********
137
+* db_url, db_ctable, db_qtable exist?
138
+**********/
139
+
140
+if (!*db_url)
141
+  {
142
+  LM_ERR ("db_url parameter not set!");
143
+  return 0;
144
+  }
145
+pmod_data->pcfg->db_url.s = db_url;
146
+pmod_data->pcfg->db_url.len = strlen (db_url);
147
+if (!*db_ctable)
148
+  {
149
+  LM_ERR ("db_ctable parameter not set!");
150
+  return 0;
151
+  }
152
+pmod_data->pcfg->db_ctable.s = db_ctable;
153
+pmod_data->pcfg->db_ctable.len = strlen (db_ctable);
154
+if (!*db_qtable)
155
+  {
156
+  LM_ERR ("db_qtable parameter not set!");
157
+  return 0;
158
+  }
159
+pmod_data->pcfg->db_qtable.s = db_qtable;
160
+pmod_data->pcfg->db_qtable.len = strlen (db_qtable);
161
+
162
+/**********
163
+* mohdir
164
+* o exists?
165
+* o directory?
166
+**********/
167
+
168
+if (!*mohdir)
169
+  {
170
+  LM_ERR ("mohdir parameter not set!");
171
+  return 0;
172
+  }
173
+if (strlen (mohdir) > MOHDIRLEN)
174
+  {
175
+  LM_ERR ("mohdir too long!");
176
+  return 0;
177
+  }
178
+pmod_data->pcfg->mohdir = mohdir;
179
+int bfnd = 0;
180
+struct stat psb [1];
181
+if (!lstat (mohdir, psb))
182
+  {
183
+  if ((psb->st_mode & S_IFMT) == S_IFDIR)
184
+    { bfnd = 1; }
185
+  }
186
+if (!bfnd)
187
+  {
188
+  LM_ERR ("mohdir is not a directory!");
189
+  return 0;
190
+  }
191
+
192
+/**********
193
+* max calls
194
+* o valid count?
195
+* o alloc memory
196
+**********/
197
+
198
+if (moh_maxcalls < 1 || moh_maxcalls > 5000)
199
+  {
200
+  LM_ERR ("moh_maxcalls not in range of 1-5000!");
201
+  return 0;
202
+  }
203
+pmod_data->pcall_lst =
204
+  (call_lst *) shm_malloc (sizeof (call_lst) * moh_maxcalls);
205
+if (!pmod_data->pcall_lst)
206
+  {
207
+  LM_ERR ("Unable to allocate shared memory");
208
+  return -1;
209
+  }
210
+memset (pmod_data->pcall_lst, 0, sizeof (call_lst) * moh_maxcalls);
211
+pmod_data->call_cnt = moh_maxcalls;
212
+return -1;
213
+}
214
+
215
+/**********
216
+* DB Initialization
217
+*
218
+* INPUT:
219
+*   pmod_data memory allocated and cfg values set
220
+* OUTPUT: 0 if failed; else pmod_data has db_api
221
+**********/
222
+
223
+static int init_db (void)
224
+
225
+{
226
+/**********
227
+* o bind to DB
228
+* o check capabilities
229
+* o init DB
230
+**********/
231
+
232
+str *pdb_url = &pmod_data->pcfg->db_url;
233
+if (db_bind_mod (pdb_url, pmod_data->pdb))
234
+  {
235
+  LM_ERR ("Unable to bind DB API using %s", pdb_url->s);
236
+  return 0;
237
+  }
238
+db_func_t *pdb = pmod_data->pdb;
239
+if (!DB_CAPABILITY ((*pdb), DB_CAP_ALL))
240
+  {
241
+  LM_ERR ("Selected database %s lacks required capabilities", pdb_url->s);
242
+  return 0;
243
+  }
244
+db1_con_t *pconn = mohq_dbconnect ();
245
+if (!pconn)
246
+  { return 0; }
247
+
248
+/**********
249
+* o check schema
250
+* o remove all call recs
251
+* o load queue list
252
+**********/
253
+
254
+if (db_check_table_version (pdb, pconn,
255
+  &pmod_data->pcfg->db_ctable, MOHQ_CTABLE_VERSION) < 0)
256
+  {
257
+  LM_ERR ("%s table in DB %s not at version %d",
258
+    pmod_data->pcfg->db_ctable.s, pdb_url->s, MOHQ_CTABLE_VERSION);
259
+  goto dberr;
260
+  }
261
+if (db_check_table_version (pdb, pconn,
262
+  &pmod_data->pcfg->db_qtable, MOHQ_QTABLE_VERSION) < 0)
263
+  {
264
+  LM_ERR ("%s table in DB %s not at version %d",
265
+    pmod_data->pcfg->db_qtable.s, pdb_url->s, MOHQ_QTABLE_VERSION);
266
+  goto dberr;
267
+  }
268
+clear_calls (pconn);
269
+update_mohq_lst (pconn);
270
+pmod_data->mohq_update = time (0);
271
+mohq_dbdisconnect (pconn);
272
+return -1;
273
+
274
+/**********
275
+* close DB
276
+**********/
277
+
278
+dberr:
279
+pdb->close (pconn);
280
+return 0;
281
+}
282
+
283
+/**********
284
+* Child Module Initialization
285
+*
286
+* INPUT:
287
+*   Arg (1) = child type
288
+* OUTPUT: -1 if db_api not ready; else 0
289
+**********/
290
+
291
+int mod_child_init (int rank)
292
+
293
+{
294
+/**********
295
+* o seed random number generator
296
+* o make sure DB initialized
297
+**********/
298
+
299
+srand (getpid () + time (0));
300
+if (rank == PROC_INIT || rank == PROC_TCP_MAIN || rank == PROC_MAIN)
301
+  { return 0; }
302
+if (!pmod_data->pdb->init)
303
+  {
304
+  LM_CRIT ("DB API not loaded!");
305
+  return -1;
306
+  }
307
+return 0;
308
+}
309
+
310
+/**********
311
+* Module Teardown
312
+*
313
+* INPUT: none
314
+* OUTPUT: none
315
+**********/
316
+
317
+void mod_destroy (void)
318
+
319
+{
320
+/**********
321
+* o destroy MOH can call queue locks
322
+* o deallocate shared mem
323
+**********/
324
+
325
+if (!pmod_data)
326
+  { return; }
327
+if (pmod_data->pmohq_lock->plock)
328
+  { mohq_lock_destroy (pmod_data->pmohq_lock); }
329
+if (pmod_data->pcall_lock->plock)
330
+  { mohq_lock_destroy (pmod_data->pcall_lock); }
331
+if (pmod_data->pmohq_lst)
332
+  { shm_free (pmod_data->pmohq_lst); }
333
+if (pmod_data->pcall_lst)
334
+  { shm_free (pmod_data->pcall_lst); }
335
+shm_free (pmod_data);
336
+return;
337
+}
338
+
339
+/**********
340
+* Module Initialization
341
+*
342
+* INPUT: none
343
+* OUTPUT: -1 if failed; 0 if success
344
+**********/
345
+
346
+int mod_init (void)
347
+
348
+{
349
+/**********
350
+* o allocate shared mem and init
351
+* o init configuration data
352
+* o init DB
353
+**********/
354
+
355
+pmod_data = (mod_data *) shm_malloc (sizeof (mod_data));
356
+if (!pmod_data)
357
+  {
358
+  LM_ERR ("Unable to allocate shared memory");
359
+  return -1;
360
+  }
361
+memset (pmod_data, 0, sizeof (mod_data));
362
+if (!init_cfg ())
363
+  { goto initerr; }
364
+if (!init_db ())
365
+  { goto initerr; }
366
+
367
+/**********
368
+* o bind to SL/TM/RR modules
369
+* o bind to RTPPROXY functions
370
+**********/
371
+
372
+if (sl_load_api (pmod_data->psl))
373
+  {
374
+  LM_ERR ("Unable to load SL module");
375
+  goto initerr;
376
+  }
377
+if (load_tm_api (pmod_data->ptm))
378
+  {
379
+  LM_ERR ("Unable to load TM module");
380
+  goto initerr;
381
+  }
382
+if (load_rr_api (pmod_data->prr))
383
+  {
384
+  LM_ERR ("Unable to load RR module");
385
+  goto initerr;
386
+  }
387
+pmod_data->fn_rtp_answer = find_export ("rtpproxy_answer", 0, 0);
388
+if (!pmod_data->fn_rtp_answer)
389
+  {
390
+  LM_ERR ("Unable to load rtpproxy_answer");
391
+  goto initerr;
392
+  }
393
+pmod_data->fn_rtp_offer = find_export ("rtpproxy_offer", 0, 0);
394
+if (!pmod_data->fn_rtp_offer)
395
+  {
396
+  LM_ERR ("Unable to load rtpproxy_offer");
397
+  goto initerr;
398
+  }
399
+pmod_data->fn_rtp_stream_c = find_export ("rtpproxy_stream2uac", 2, 0);
400
+if (!pmod_data->fn_rtp_stream_c)
401
+  {
402
+  LM_ERR ("Unable to load rtpproxy_stream2uac");
403
+  goto initerr;
404
+  }
405
+pmod_data->fn_rtp_stream_s = find_export ("rtpproxy_stream2uas", 2, 0);
406
+if (!pmod_data->fn_rtp_stream_s)
407
+  {
408
+  LM_ERR ("Unable to load rtpproxy_stream2uas");
409
+  goto initerr;
410
+  }
411
+pmod_data->fn_rtp_destroy = find_export ("rtpproxy_destroy", 0, 0);
412
+if (!pmod_data->fn_rtp_destroy)
413
+  {
414
+  LM_ERR ("Unable to load rtpproxy_destroy");
415
+  goto initerr;
416
+  }
417
+
418
+/**********
419
+* init MOH and call queue locks
420
+**********/
421
+
422
+if (!mohq_lock_init (pmod_data->pmohq_lock))
423
+  { goto initerr; }
424
+if (!mohq_lock_init (pmod_data->pcall_lock))
425
+  { goto initerr; }
426
+return 0;
427
+
428
+/**********
429
+* o release shared mem
430
+* o exit with error
431
+**********/
432
+
433
+initerr:
434
+if (pmod_data->mohq_cnt)
435
+  { shm_free (pmod_data->pmohq_lst); }
436
+if (pmod_data->pcall_lock->plock)
437
+  { mohq_lock_destroy (pmod_data->pcall_lock); }
438
+shm_free (pmod_data);
439
+pmod_data = NULL;
440
+return -1;
441
+}
0 442
\ No newline at end of file
1 443
new file mode 100644
... ...
@@ -0,0 +1,132 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2013 Robert Boisvert
4
+ *
5
+ * This file is part of the mohqueue module for sip-router, a free SIP server.
6
+ *
7
+ * The mohqueue module is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * The mohqueue module is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
+ *
21
+ */
22
+
23
+#ifndef MOHQ_H
24
+#define MOHQ_H
25
+
26
+#include "mohq_common.h"
27
+#include "mohq_locks.h"
28
+
29
+/**********
30
+* definitions
31
+**********/
32
+
33
+#define URI_LEN     100
34
+#define USLEEP_LEN  10
35
+#define MOHDIRLEN   100
36
+#define MOHFILELEN  100
37
+
38
+/**********
39
+* structures
40
+**********/
41
+
42
+typedef struct
43
+  {
44
+  int ntype;
45
+  char *pencode;
46
+  } rtpmap;
47
+
48
+/* mohq_flags values */
49
+#define MOHQF_ACT 0x01
50
+#define MOHQF_CHK 0x02
51
+#define MOHQF_DBG 0x04
52
+
53
+typedef struct
54
+  {
55
+  char mohq_name [26];
56
+  char mohq_uri [URI_LEN + 1];
57
+  char mohq_mohdir [MOHDIRLEN + 1];
58
+  char mohq_mohfile [MOHFILELEN + 1];
59
+  int mohq_flags;
60
+  int mohq_id;
61
+  } mohq_lst;
62
+
63
+/* call_state values */
64
+#define CLSTA_ENTER     100
65
+#define CLSTA_PRACKSTRT 101
66
+#define CLSTA_PRACKRPLY 102
67
+#define CLSTA_RINGING   103
68
+#define CLSTA_INVITED   104
69
+#define CLSTA_CANCEL    105
70
+#define CLSTA_INQUEUE   200
71
+#define CLSTA_REFER     301
72
+#define CLSTA_RFRWAIT   302
73
+#define CLSTA_BYE       305
74
+
75
+typedef struct
76
+  {
77
+  int call_active;
78
+  char call_id [101];
79
+  char call_from [URI_LEN + 1];
80
+  char call_referto [URI_LEN + 1];
81
+  char call_contact [URI_LEN + 1];
82
+  char call_tag [101];
83
+  char call_via [1024];
84
+  char call_addr [IP_ADDR_MAX_STR_SIZE + 4];
85
+  int call_state;
86
+  int call_cseq;
87
+  int call_aport;
88
+  mohq_lst *pmohq;
89
+  time_t call_time;
90
+  unsigned int call_hash;
91
+  unsigned int call_label;
92
+  sip_msg_t *call_pmsg;
93
+  } call_lst;
94
+
95
+typedef struct
96
+  {
97
+  char *mohdir;
98
+  str db_url;
99
+  str db_ctable;
100
+  str db_qtable;
101
+  } mod_cfg;
102
+
103
+typedef struct
104
+  {
105
+  mod_cfg pcfg [1];
106
+  time_t mohq_update;
107
+  int mohq_cnt;
108
+  mohq_lst *pmohq_lst;
109
+  mohq_lock pmohq_lock [1];
110
+  int call_cnt;
111
+  call_lst *pcall_lst;
112
+  mohq_lock pcall_lock [1];
113
+  db_func_t pdb [1];
114
+  tm_api_t ptm [1];
115
+  sl_api_t psl [1];
116
+  rr_api_t prr [1];
117
+  cmd_function fn_rtp_answer;
118
+  cmd_function fn_rtp_destroy;
119
+  cmd_function fn_rtp_offer;
120
+  cmd_function fn_rtp_stream_c;
121
+  cmd_function fn_rtp_stream_s;
122
+  } mod_data;
123
+
124
+/**********
125
+* global varb declarations
126
+**********/
127
+
128
+extern mod_data *pmod_data;
129
+extern rtpmap prtpmap [];
130
+
131
+#endif /* MOHQ_H */
0 132
\ No newline at end of file
1 133
new file mode 100644
... ...
@@ -0,0 +1,104 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2013 Robert Boisvert
4
+ *
5
+ * This file is part of the mohqueue module for sip-router, a free SIP server.
6
+ *
7
+ * The mohqueue module is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * The mohqueue module is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
+ *
21
+ */
22
+
23
+#ifndef MOHQ_COMMON_H
24
+#define MOHQ_COMMON_H
25
+
26
+#include <assert.h>
27
+#include <sys/stat.h>
28
+
29
+#include "../rr/api.h"
30
+
31
+#include "../../data_lump.h"
32
+#include "../../data_lump_rpl.h"
33
+#include "../../dprint.h"
34
+#include "../../dset.h"
35
+#include "../../flags.h"
36
+#include "../../hashes.h"
37
+#include "../../locking.h"
38
+#include "../../lvalue.h"
39
+#include "../../mod_fix.h"
40
+#include "../../sr_module.h"
41
+#include "../../str.h"
42
+
43
+#include "../../lib/kcore/cmpapi.h"
44
+#include "../../lib/kmi/mi.h"
45
+#include "../../lib/srdb1/db.h"
46
+#include "../../mem/mem.h"
47
+#include "../../mem/shm_mem.h"
48
+#include "../../modules/sl/sl.h"
49
+#include "../../modules/tm/tm_load.h"
50
+#include "../../parser/hf.h"
51
+#include "../../parser/msg_parser.h"
52
+#include "../../parser/contact/parse_contact.h"
53
+#include "../../parser/parse_expires.h"
54
+#include "../../parser/parse_from.h"
55
+#include "../../parser/sdp/sdp.h"
56
+
57
+/* convenience macros */
58
+#define MOHQ_STRUCT_PTR_OFFSET( struct1, cast1, offset1 ) \
59
+	(cast1)(struct1) + (offset1)
60
+	
61
+#define MOHQ_STR_COPY( str1, str2 ) \
62
+	memcpy((str1)->s, (str2)->s, (str2)->len ); \
63
+	(str1)->len = (str2)->len;
64
+
65
+#define MOHQ_STR_APPEND( str1, str2 ) \
66
+	memcpy((str1)->s + (str1)->len, (str2)->s, (str2)->len); \
67