Browse code

modules_k/rls: added DB only mode to rls

- By using DB only mode RLS can be distributed across many Kamailio
servers for scaling and resilience.
- This change has been in use internally at Crocodile RCS for some time,
but it is extensive.
- The DB only mode changes have been made in a way that changes the pre-
existing (hash-table based) mode of operation as little as possible.
This original mode of operation SHOULD be unaffected by this change.
- This enhancement was made by Paul Pankhurst at Crocodile RCS.
- Also contains a small bug-fix to RLS indices by Hugh Waite.
- I have also exported the RLS API for use in app_lua

pd authored on 19/10/2011 11:52:21
Showing 9 changed files
... ...
@@ -1,3 +1,4 @@
1
+
1 2
 Resource List Server
2 3
 
3 4
 Anca-Maria Vamanu
... ...
@@ -8,8 +9,8 @@ Edited by
8 9
 
9 10
 Anca-Maria Vamanu
10 11
 
11
-   Copyright © 2007 Voice Sistem SRL
12
-     __________________________________________________________________
12
+   Copyright � 2007 Voice Sistem SRL
13
+     _________________________________________________________________
13 14
 
14 15
    Table of Contents
15 16
 
... ...
@@ -24,26 +25,29 @@ Anca-Maria Vamanu
24 25
         3. Parameters
25 26
 
26 27
               3.1. db_url(str)
27
-              3.2. xcap_table(str)
28
-              3.3. rlsubs_table(str)
29
-              3.4. rlpres_table(str)
30
-              3.5. clean_period (int)
31
-              3.6. waitn_time (int)
32
-              3.7. max_expires (int)
33
-              3.8. hash_size (int)
34
-              3.9. xcap_root (str)
35
-              3.10. integrated_xcap_server (int)
36
-              3.11. to_presence_code (int)
37
-              3.12. rls_event (str)
38
-              3.13. outbound_proxy (str)
39
-              3.14. server_address (str)
40
-              3.15. max_notify_body_length (int)
28
+              3.2. xcap_db_url(str)
29
+              3.3. db_mode(int)
30
+              3.4. xcap_table(str)
31
+              3.5. rlsubs_table(str)
32
+              3.6. rlpres_table(str)
33
+              3.7. clean_period (int)
34
+              3.8. waitn_time (int)
35
+              3.9. max_expires (int)
36
+              3.10. expires_offset (int)
37
+              3.11. hash_size (int)
38
+              3.12. xcap_root (str)
39
+              3.13. integrated_xcap_server (int)
40
+              3.14. to_presence_code (int)
41
+              3.15. rls_event (str)
42
+              3.16. outbound_proxy (str)
43
+              3.17. server_address (str)
44
+              3.18. max_notify_body_length (int)
41 45
 
42 46
         4. Functions
43 47
 
44
-              4.1. rls_handle_subscribe()
45
-              4.2. rls_handle_notify()
46
-              4.3. rls_update_subs(uri, event)
48
+              4.1. rls_handle_subscribe() 
49
+              4.2. rls_handle_notify() 
50
+              4.3. rls_update_subs(uri, event) 
47 51
 
48 52
         5. Installation
49 53
 
... ...
@@ -52,23 +56,26 @@ Anca-Maria Vamanu
52 56
    List of Examples
53 57
 
54 58
    1.1. Set db_url parameter
55
-   1.2. Set xcap_table parameter
56
-   1.3. Set rlsubs_table parameter
57
-   1.4. Set rlpres_table parameter
58
-   1.5. Set clean_period parameter
59
-   1.6. Set waitn_time parameter
60
-   1.7. Set max_expires parameter
61
-   1.8. Set hash_size parameter
62
-   1.9. Set hash_size parameter
63
-   1.10. Set integrated_xcap_server parameter
64
-   1.11. Set to_presence_code parameter
65
-   1.12. Set rls_event parameter
66
-   1.13. Set outbound_proxy parameter
67
-   1.14. Set server_address parameter
68
-   1.15. Set max_notify_body_length parameter
69
-   1.16. rls_handle_subscribe usage
70
-   1.17. rls_handle_notify usage
71
-   1.18. rls_update_subs usage
59
+   1.2. Set xcap_db_url parameter
60
+   1.3. Set db_mode parameter
61
+   1.4. Set xcap_table parameter
62
+   1.5. Set rlsubs_table parameter
63
+   1.6. Set rlpres_table parameter
64
+   1.7. Set clean_period parameter
65
+   1.8. Set waitn_time parameter
66
+   1.9. Set max_expires parameter
67
+   1.10. Set expires_offset parameter
68
+   1.11. Set hash_size parameter
69
+   1.12. Set hash_size parameter
70
+   1.13. Set integrated_xcap_server parameter
71
+   1.14. Set to_presence_code parameter
72
+   1.15. Set rls_event parameter
73
+   1.16. Set outbound_proxy parameter
74
+   1.17. Set server_address parameter
75
+   1.18. Set max_notify_body_length parameter
76
+   1.19. rls_handle_subscribe usage
77
+   1.20. rls_handle_notify usage
78
+   1.21. rls_update_subs usage
72 79
 
73 80
 Chapter 1. Admin Guide
74 81
 
... ...
@@ -83,57 +90,60 @@ Chapter 1. Admin Guide
83 90
    3. Parameters
84 91
 
85 92
         3.1. db_url(str)
86
-        3.2. xcap_table(str)
87
-        3.3. rlsubs_table(str)
88
-        3.4. rlpres_table(str)
89
-        3.5. clean_period (int)
90
-        3.6. waitn_time (int)
91
-        3.7. max_expires (int)
92
-        3.8. hash_size (int)
93
-        3.9. xcap_root (str)
94
-        3.10. integrated_xcap_server (int)
95
-        3.11. to_presence_code (int)
96
-        3.12. rls_event (str)
97
-        3.13. outbound_proxy (str)
98
-        3.14. server_address (str)
99
-        3.15. max_notify_body_length (int)
93
+        3.2. xcap_db_url(str)
94
+        3.3. db_mode(int)
95
+        3.4. xcap_table(str)
96
+        3.5. rlsubs_table(str)
97
+        3.6. rlpres_table(str)
98
+        3.7. clean_period (int)
99
+        3.8. waitn_time (int)
100
+        3.9. max_expires (int)
101
+        3.10. expires_offset (int)
102
+        3.11. hash_size (int)
103
+        3.12. xcap_root (str)
104
+        3.13. integrated_xcap_server (int)
105
+        3.14. to_presence_code (int)
106
+        3.15. rls_event (str)
107
+        3.16. outbound_proxy (str)
108
+        3.17. server_address (str)
109
+        3.18. max_notify_body_length (int)
100 110
 
101 111
    4. Functions
102 112
 
103
-        4.1. rls_handle_subscribe()
104
-        4.2. rls_handle_notify()
105
-        4.3. rls_update_subs(uri, event)
113
+        4.1. rls_handle_subscribe() 
114
+        4.2. rls_handle_notify() 
115
+        4.3. rls_update_subs(uri, event) 
106 116
 
107 117
    5. Installation
108 118
 
109 119
 1. Overview
110 120
 
111
-   The modules is a Resource List Server implementation following the
121
+   The  modules  is  a  Resource List Server implementation following the
112 122
    specification in RFC 4662 and RFC 4826.
113 123
 
114
-   The server is independent from local presence servers, retrieving
124
+   The  server  is  independent  from  local presence servers, retrieving
115 125
    presence information with Subscribe-Notify messages.
116 126
 
117
-   The module uses the presence module as a library, as it requires a
118
-   resembling mechanism for handling Subscribe. Therefore, in case the
119
-   local presence server is not collocated on the same machine with the RL
120
-   server, the presence module should be loaded in a library mode only
127
+   The  module  uses  the  presence module as a library, as it requires a
128
+   resembling  mechanism  for  handling Subscribe. Therefore, in case the
129
+   local  presence  server is not collocated on the same machine with the
130
+   RL server, the presence module should be loaded in a library mode only
121 131
    (see doc for presence module).
122 132
 
123
-   It handles subscription to lists in an event independent way.The
124
-   default event is presence, but if some other events are to be handled
125
-   by the server, they should be added using the module parameter
133
+   It  handles  subscription  to  lists  in  an event independent way.The
134
+   default  event is presence, but if some other events are to be handled
135
+   by  the  server,  they  should  be  added  using  the module parameter
126 136
    "rls_events".
127 137
 
128
-   It works with XCAP server for storage. There is also the possibility to
129
-   configure it to work in an integrated_xcap server mode, when it only
130
-   queries database for the resource lists documents. This is useful in a
131
-   small architecture when all the clients use an integrated server and
132
-   there are no references to exterior documents in their lists.
138
+   It  works  with XCAP server for storage. There is also the possibility
139
+   to  configure  it  to  work in an integrated_xcap server mode, when it
140
+   only queries database for the resource lists documents. This is useful
141
+   in  a small architecture when all the clients use an integrated server
142
+   and there are no references to exterior documents in their lists.
133 143
 
134
-   The same as presence module, it has a caching mode with periodical
135
-   update in database for subscribe information. The information retrieved
136
-   with Notify messages is stored in database only.
144
+   The  same  as  presence  module, it has a caching mode with periodical
145
+   update   in   database  for  subscribe  information.  The  information
146
+   retrieved with Notify messages is stored in database only.
137 147
 
138 148
 2. Dependencies
139 149
 
... ...
@@ -156,219 +166,266 @@ Chapter 1. Admin Guide
156 166
 3. Parameters
157 167
 
158 168
    3.1. db_url(str)
159
-   3.2. xcap_table(str)
160
-   3.3. rlsubs_table(str)
161
-   3.4. rlpres_table(str)
162
-   3.5. clean_period (int)
163
-   3.6. waitn_time (int)
164
-   3.7. max_expires (int)
165
-   3.8. hash_size (int)
166
-   3.9. xcap_root (str)
167
-   3.10. integrated_xcap_server (int)
168
-   3.11. to_presence_code (int)
169
-   3.12. rls_event (str)
170
-   3.13. outbound_proxy (str)
171
-   3.14. server_address (str)
172
-   3.15. max_notify_body_length (int)
169
+   3.2. xcap_db_url(str)
170
+   3.3. db_mode(int)
171
+   3.4. xcap_table(str)
172
+   3.5. rlsubs_table(str)
173
+   3.6. rlpres_table(str)
174
+   3.7. clean_period (int)
175
+   3.8. waitn_time (int)
176
+   3.9. max_expires (int)
177
+   3.10. expires_offset (int)
178
+   3.11. hash_size (int)
179
+   3.12. xcap_root (str)
180
+   3.13. integrated_xcap_server (int)
181
+   3.14. to_presence_code (int)
182
+   3.15. rls_event (str)
183
+   3.16. outbound_proxy (str)
184
+   3.17. server_address (str)
185
+   3.18. max_notify_body_length (int)
173 186
 
174 187
 3.1. db_url(str)
175 188
 
176 189
    The database url.
177 190
 
178
-   Default value is “mysql://openser:openserrw@localhost/openser”.
191
+   Default value is "mysql://openser:openserrw@localhost/openser". 
179 192
 
180 193
    Example 1.1. Set db_url parameter
181 194
 ...
182 195
 modparam("rls", "db_url", "dbdriver://username:password@dbhost/dbname")
183 196
 ...
184 197
 
185
-3.2. xcap_table(str)
198
+3.2. xcap_db_url(str)
199
+
200
+   The  xcap  database  url. This parameter only needs to be specified if
201
+   the rls db and integerated xcap server db have different urls.
202
+
203
+   Default value is a mirror of the "db_url" setting. 
204
+
205
+   Example 1.2. Set xcap_db_url parameter
206
+...
207
+modparam("rls", "xcap_db_url", "dbdriver://username:password@dbhost/dbname")
208
+...
209
+
210
+3.3. db_mode(int)
211
+
212
+   The  module  supports  2  modes  of operation, high speed memory based
213
+   storage  (mode 0), and database only (mode 2) where all data is stored
214
+   in a database, allowing scalability at the expense of speed. Mode 1 is
215
+   reserved.
186 216
 
187
-   The name of the xcap table in which the integrated server or the
188
-   xcap_client module writes. If integrated_xcap_server parameter not set,
189
-   the name of the table must be the same as the one set for the
217
+   Default value is "0" 
218
+
219
+   Example 1.3. Set db_mode parameter
220
+...
221
+modparam("rls", "db_mode", 2)
222
+...
223
+
224
+3.4. xcap_table(str)
225
+
226
+   The  name  of  the  xcap  table  in which the integrated server or the
227
+   xcap_client  module  writes.  If  integrated_xcap_server parameter not
228
+   set,  the  name  of  the table must be the same as the one set for the
190 229
    xcap_client module.
191 230
 
192
-   Default value is “xcap”.
231
+   Default value is "xcap". 
193 232
 
194
-   Example 1.2. Set xcap_table parameter
233
+   Example 1.4. Set xcap_table parameter
195 234
 ...
196 235
 modparam("rls", "xcap_table", "xcaps");
197 236
 ...
198 237
 
199
-3.3. rlsubs_table(str)
238
+3.5. rlsubs_table(str)
200 239
 
201 240
    The name of the db table where resource lists subscription information
202 241
    is stored.
203 242
 
204
-   Default value is “rls_watchers”.
243
+   Default value is "rls_watchers". 
205 244
 
206
-   Example 1.3. Set rlsubs_table parameter
245
+   Example 1.5. Set rlsubs_table parameter
207 246
 ...
208 247
 modparam("rls", "rlsubs_table", "rls_subscriptions")
209 248
 ...
210 249
 
211
-3.4. rlpres_table(str)
250
+3.6. rlpres_table(str)
212 251
 
213
-   The name of the db table where notified event specific information is
252
+   The  name of the db table where notified event specific information is
214 253
    stored.
215 254
 
216
-   Default value is “rls_presentity”.
255
+   Default value is "rls_presentity". 
217 256
 
218
-   Example 1.4. Set rlpres_table parameter
257
+   Example 1.6. Set rlpres_table parameter
219 258
 ...
220 259
 modparam("rls", "rlpres_table", "rls_notify")
221 260
 ...
222 261
 
223
-3.5. clean_period (int)
262
+3.7. clean_period (int)
224 263
 
225 264
    The period at which to check for expired information.
226 265
 
227
-   Default value is “100”.
266
+   Default value is "100". 
228 267
 
229
-   Example 1.5. Set clean_period parameter
268
+   Example 1.7. Set clean_period parameter
230 269
 ...
231 270
 modparam("rls", "clean_period", 100)
232 271
 ...
233 272
 
234
-3.6. waitn_time (int)
273
+3.8. waitn_time (int)
235 274
 
236
-   The timer period at which the server should attempt to send Notifies
237
-   with the updated presence state of the subscribed list or watcher
275
+   The  timer  period at which the server should attempt to send Notifies
276
+   with  the  updated  presence  state  of the subscribed list or watcher
238 277
    information.
239 278
 
240
-   Default value is “50”.
279
+   Default value is "50". 
241 280
 
242
-   Example 1.6. Set waitn_time parameter
281
+   Example 1.8. Set waitn_time parameter
243 282
 ...
244 283
 modparam("rls", "waitn_time", 10)
245 284
 ...
246 285
 
247
-3.7. max_expires (int)
286
+3.9. max_expires (int)
248 287
 
249 288
    The maximum accepted expires for a subscription to a list.
250 289
 
251
-   Default value is “7200”.
290
+   Default value is "7200". 
252 291
 
253
-   Example 1.7. Set max_expires parameter
292
+   Example 1.9. Set max_expires parameter
254 293
 ...
255 294
 modparam("rls", "max_expires", 10800)
256 295
 ...
257 296
 
258
-3.8. hash_size (int)
297
+3.10. expires_offset (int)
298
+
299
+   This  paramater  only  has an effect when the db_mode is DB_ONLY (mode
300
+   2).  When  expired  subscribers  are  checked  for  deletion  from the
301
+   database,  those that have a value in the expires column which is less
302
+   than  current_time  - expires_offset are matched. Hence when an offset
303
+   of  zero is used, all those that expire prior the current time will be
304
+   deleted.  If  an  offset  of 't' is used, only those that expired more
305
+   than t seconds ago are deleted from the database. Negative offsets are
306
+   treated as though an offset of zero was specifed.
307
+
308
+   Default value is "0". 
309
+
310
+   Example 1.10. Set expires_offset parameter
311
+...
312
+modparam("rls", "expires_offset", 0)
313
+...
314
+
315
+3.11. hash_size (int)
259 316
 
260
-   The dimension of the hash table used to store subscription to a list.
261
-   This parameter will be used as the power of 2 when computing table
317
+   The  dimension of the hash table used to store subscription to a list.
318
+   This  parameter  will  be  used as the power of 2 when computing table
262 319
    size.
263 320
 
264
-   Default value is “9 (512)”.
321
+   Default value is "9 (512)". 
265 322
 
266
-   Example 1.8. Set hash_size parameter
323
+   Example 1.11. Set hash_size parameter
267 324
 ...
268 325
 modparam("rls", "hash_size", 11)
269 326
 ...
270 327
 
271
-3.9. xcap_root (str)
328
+3.12. xcap_root (str)
272 329
 
273 330
    The address of the xcap server.
274 331
 
275
-   Default value is “NULL”.
332
+   Default value is "NULL". 
276 333
 
277
-   Example 1.9. Set hash_size parameter
334
+   Example 1.12. Set hash_size parameter
278 335
 ...
279 336
 modparam("rls", "xcap_root", "http://192.168.2.132/xcap-root:800")
280 337
 ...
281 338
 
282
-3.10. integrated_xcap_server (int)
339
+3.13. integrated_xcap_server (int)
283 340
 
284
-   This parameter should be set if only integrated xcap servers are used
341
+   This  parameter should be set if only integrated xcap servers are used
285 342
    to store resource lists.
286 343
 
287
-   Default value is “0”.
344
+   Default value is "0". 
288 345
 
289
-   Example 1.10. Set integrated_xcap_server parameter
346
+   Example 1.13. Set integrated_xcap_server parameter
290 347
 ...
291 348
 modparam("rls", "integrated_xcap_server", 1)
292 349
 ...
293 350
 
294
-3.11. to_presence_code (int)
351
+3.14. to_presence_code (int)
295 352
 
296
-   The code to be returned by rls_handle_subscribe function if the
353
+   The  code  to  be  returned  by  rls_handle_subscribe  function if the
297 354
    processed Subscribe is not a resource list Subscribe. This code can be
298
-   used in an architecture with presence and rls servers collocated on the
299
-   same machine, to call handle_subscribe on the message causing this
355
+   used  in  an  architecture with presence and rls servers collocated on
356
+   the same machine, to call handle_subscribe on the message causing this
300 357
    code.
301 358
 
302
-   Default value is “0”.
359
+   Default value is "0". 
303 360
 
304
-   Example 1.11. Set to_presence_code parameter
361
+   Example 1.14. Set to_presence_code parameter
305 362
 ...
306 363
 modparam("rls", "to_presence_code", 10)
307 364
 ...
308 365
 
309
-3.12. rls_event (str)
366
+3.15. rls_event (str)
310 367
 
311
-   The default event that RLS handles is presence. If some other events
312
-   should also be handled by RLS they should be added using this
368
+   The  default  event that RLS handles is presence. If some other events
369
+   should  also  be  handled  by  RLS  they  should  be  added using this
313 370
    parameter. It can be set more than once.
314 371
 
315
-   Default value is “"presence"”.
372
+   Default value is ""presence"". 
316 373
 
317
-   Example 1.12. Set rls_event parameter
374
+   Example 1.15. Set rls_event parameter
318 375
 ...
319 376
 modparam("rls", "rls_event", "dialog;sla")
320 377
 ...
321 378
 
322
-3.13. outbound_proxy (str)
379
+3.16. outbound_proxy (str)
323 380
 
324
-   The SIP address where to send RLS subscriptions (outbound proxy address
325
-   as SIP URI).
381
+   The  SIP  address  where  to  send  RLS  subscriptions (outbound proxy
382
+   address as SIP URI).
326 383
 
327
-   Default value is “NULL”.
384
+   Default value is "NULL". 
328 385
 
329
-   Example 1.13. Set outbound_proxy parameter
386
+   Example 1.16. Set outbound_proxy parameter
330 387
 ...
331 388
 modparam("rls", "outbound_proxy", "sip:presence.kamailio.org")
332 389
 ...
333 390
 
334
-3.14. server_address (str)
391
+3.17. server_address (str)
335 392
 
336
-   The address of the server that will be used as a contact in sent
337
-   Subscribe requests and 200 OK replies for Subscribe requests for RLS.
393
+   The  address  of  the  server  that  will be used as a contact in sent
394
+   Subscribe  requests and 200 OK replies for Subscribe requests for RLS.
338 395
    It is a mandatory parameter.
339 396
 
340
-   Example 1.14. Set server_address parameter
397
+   Example 1.17. Set server_address parameter
341 398
 ...
342 399
 modparam("rls", "server_address", "sip:rls@ip.address.ofyour.proxy:5060")
343 400
 ...
344 401
 
345
-3.15. max_notify_body_length (int)
402
+3.18. max_notify_body_length (int)
346 403
 
347 404
    The maximum size that the body of a NOTIFY message may be. If set to 0
348 405
    (the default), no size limit is applied. Note that this refers only to
349 406
    the body, not the complete NOTIFY message.
350 407
 
351
-   Example 1.15. Set max_notify_body_length parameter
408
+   Example 1.18. Set max_notify_body_length parameter
352 409
 ...
353 410
 modparam("rls", "max_notify_body_length", 32000)
354 411
 ...
355 412
 
356 413
 4. Functions
357 414
 
358
-   4.1. rls_handle_subscribe()
359
-   4.2. rls_handle_notify()
360
-   4.3. rls_update_subs(uri, event)
415
+   4.1. rls_handle_subscribe() 
416
+   4.2. rls_handle_notify() 
417
+   4.3. rls_update_subs(uri, event) 
361 418
 
362 419
 4.1.  rls_handle_subscribe()
363 420
 
364 421
    This function detects if a Subscribe message should be handled by RLS.
365
-   If not it replies with the configured to_presence_code. If it is, it
366
-   extracts the dialog info and sends aggregate Notify requests with
422
+   If  not  it replies with the configured to_presence_code. If it is, it
423
+   extracts  the  dialog  info  and  sends aggregate Notify requests with
367 424
    information for the list.
368 425
 
369 426
    This function can be used from REQUEST_ROUTE.
370 427
 
371
-   Example 1.16. rls_handle_subscribe usage
428
+   Example 1.19. rls_handle_subscribe usage
372 429
 ...
373 430
 For presence and rls on the same machine:
374 431
         modparam("rls", "to_presence_code", 10)
... ...
@@ -396,7 +453,7 @@ For rls only:
396 453
 
397 454
    This function can be used from REQUEST_ROUTE.
398 455
 
399
-   Example 1.17. rls_handle_notify usage
456
+   Example 1.20. rls_handle_notify usage
400 457
 ...
401 458
 if(method=="NOTIFY")
402 459
     rls_handle_notify();
... ...
@@ -404,18 +461,18 @@ if(method=="NOTIFY")
404 461
 
405 462
 4.3.  rls_update_subs(uri, event)
406 463
 
407
-   This function can be used in configuration to trigger updates to
408
-   resource list subscriptions (for example, after the contents of a
464
+   This  function  can  be  used  in  configuration to trigger updates to
465
+   resource  list  subscriptions  (for  example,  after the contents of a
409 466
    resource list has changes).
410 467
 
411 468
    Parameters:
412
-     * uri - the uri of the user who made the change and whose resource
469
+     * uri  -  the uri of the user who made the change and whose resource
413 470
        list subscriptions should be updated
414 471
      * event - the event package (e.g. presence).
415 472
 
416 473
    This function can be used from ANY_ROUTE.
417 474
 
418
-   Example 1.18. rls_update_subs usage
475
+   Example 1.21. rls_update_subs usage
419 476
 ...
420 477
 Within event_route[xhttp:request]:
421 478
         case "PUT":
... ...
@@ -433,10 +490,10 @@ Within event_route[xhttp:request]:
433 490
 
434 491
 5. Installation
435 492
 
436
-   The module requires 2 tables in Kamailio database: rls_presentity and
437
-   rls_watchers.The SQL syntax to create them can be found in
438
-   rls-create.sql script in the database directories in the
439
-   kamailio/scripts folder. You can also find the complete database
493
+   The  module requires 2 tables in Kamailio database: rls_presentity and
494
+   rls_watchers.The   SQL   syntax   to  create  them  can  be  found  in
495
+   rls-create.sql   script   in   the   database   directories   in   the
496
+   kamailio/scripts  folder.  You  can  also  find  the complete database
440 497
    documentation on the project webpage,
441 498
    http://www.kamailio.org/docs/db-tables/kamailio-db-devel.html.
442 499
 
443 500
new file mode 100644
... ...
@@ -0,0 +1,28 @@
1
+#ifndef RLS_API_H
2
+#define RLS_API_H
3
+#include "../../str.h"
4
+
5
+typedef int (*rls_handle_subscribe_t)(struct sip_msg*, char*, char*);
6
+typedef int (*rls_handle_notify_t)(struct sip_msg*, char*, char*);
7
+
8
+typedef struct rls_binds {
9
+	rls_handle_subscribe_t rls_handle_subscribe;
10
+	rls_handle_notify_t rls_handle_notify;
11
+} rls_api_t;
12
+
13
+typedef int (*bind_rls_f)(rls_api_t*);
14
+
15
+int bind_rls(struct rls_binds*);
16
+
17
+inline static int rls_load_api(rls_api_t *pxb)
18
+{
19
+	bind_rls_f bind_rls_exports;
20
+	if (!(bind_rls_exports = (bind_rls_f)find_export("bind_rls", 1, 0)))
21
+	{
22
+		LM_ERR("Failed to import bind_rls\n");
23
+		return -1;
24
+	}
25
+	return bind_rls_exports(pxb);
26
+}
27
+
28
+#endif /*RLS_API_H*/
... ...
@@ -118,6 +118,50 @@ modparam("rls", "db_url", "&exampledb;")
118 118
 </programlisting>
119 119
 		</example>
120 120
 	</section>
121
+
122
+	<section>
123
+		<title><varname>xcap_db_url</varname>(str)</title>
124
+		<para>
125
+		The xcap database url.
126
+		This parameter only needs to be specified if the rls db and integerated 
127
+		xcap server db have different urls. 
128
+		</para>
129
+		<para>
130
+		<emphasis>	Default value is a mirror of the <quote>db_url</quote> setting.	
131
+		</emphasis>
132
+		</para>
133
+		<example>
134
+		<title>Set <varname>xcap_db_url</varname> parameter</title>
135
+		<programlisting format="linespecific">
136
+...
137
+modparam("rls", "xcap_db_url", "&exampledb;")
138
+...
139
+</programlisting>
140
+		</example>
141
+	</section>
142
+
143
+	<section>
144
+		<title><varname>db_mode</varname>(int)</title>
145
+		<para>
146
+		The module supports 2 modes of operation, high speed memory
147
+		based storage (mode 0), and database only (mode 2) where all 
148
+		data is stored in a database, allowing scalability at the expense of speed.
149
+		Mode 1 is reserved.
150
+		</para>
151
+		<para>
152
+		<emphasis>	Default value is <quote>0</quote> 	
153
+		</emphasis>
154
+		</para>
155
+		<example>
156
+		<title>Set <varname>db_mode</varname> parameter</title>
157
+		<programlisting format="linespecific">
158
+...
159
+modparam("rls", "db_mode", 2)
160
+...
161
+</programlisting>
162
+		</example>
163
+	</section>
164
+
121 165
 	<section>
122 166
 		<title><varname>xcap_table</varname>(str)</title>
123 167
 		<para>
... ...
@@ -233,6 +277,32 @@ modparam("rls", "waitn_time", 10)
233 277
 		<programlisting format="linespecific">
234 278
 ...
235 279
 modparam("rls", "max_expires", 10800)
280
+...
281
+		</programlisting>
282
+		</example>
283
+	</section>
284
+
285
+	<section>
286
+		<title><varname>expires_offset</varname> (int)</title>
287
+		<para>
288
+		This paramater only has an effect when the db_mode is DB_ONLY (mode 2).
289
+		When expired subscribers are checked for deletion from the database,
290
+		those that have a value in the expires column which is less than 
291
+		current_time - expires_offset are matched. Hence when an offset of zero
292
+		is used, all those that expire prior the current time will be deleted.
293
+		If an offset of 't' is used, only those that expired more than t seconds
294
+		ago are deleted from the database. 
295
+		Negative offsets are treated as though an offset of zero was specifed. 
296
+		</para>
297
+		<para>
298
+		<emphasis>Default value is <quote>0</quote>.
299
+		</emphasis>
300
+		</para>
301
+		<example>
302
+		<title>Set <varname>expires_offset</varname> parameter</title>
303
+		<programlisting format="linespecific">
304
+...
305
+modparam("rls", "expires_offset", 0)
236 306
 ...
237 307
 		</programlisting>
238 308
 		</example>
... ...
@@ -341,11 +341,23 @@ int agg_body_sendn_update(str* rl_uri, char* boundary_string, str* rlmi_body,
341 341
 	pkg_free(body.s);
342 342
 	body.s= NULL;
343 343
 
344
-	if(pres_update_shtable(rls_table, hash_code,subs, LOCAL_TYPE)< 0)
344
+	if (dbmode==RLS_DB_ONLY)
345 345
 	{
346
-		LM_ERR("updating in hash table\n");
347
-		goto error;
346
+		if ( update_rlsdb(subs, LOCAL_TYPE) <0 )
347
+		{
348
+			LM_ERR( "updating DB\n" );
349
+			goto error;
350
+		}
348 351
 	}
352
+	else
353
+	{
354
+		if(pres_update_shtable(rls_table, hash_code,subs, LOCAL_TYPE)< 0)
355
+		{
356
+			LM_ERR("updating in hash table\n");
357
+			goto error;
358
+		}
359
+	}
360
+
349 361
 	return 0;
350 362
 
351 363
 error:
... ...
@@ -884,7 +896,6 @@ void rls_notify_callback( struct cell *t, int type, struct tmcb_params *ps)
884 896
 
885 897
 	if(ps->code >= 300)
886 898
 	{
887
-		/* delete from database table */
888 899
 		db_key_t db_keys[2];
889 900
 		db_val_t db_vals[2];
890 901
 		unsigned int hash_code;
... ...
@@ -896,32 +907,48 @@ void rls_notify_callback( struct cell *t, int type, struct tmcb_params *ps)
896 907
 		subs.from_tag= ((dialog_id_t*)(*ps->param))->from_tag;
897 908
 		subs.callid= ((dialog_id_t*)(*ps->param))->callid;
898 909
 
899
-		if (rls_dbf.use_table(rls_db, &rlsubs_table) < 0) 
910
+		if (dbmode != RLS_DB_ONLY)
900 911
 		{
901
-			LM_ERR("in use_table\n");
902
-			goto done;
903
-		}
912
+			/* delete from database table */
913
+
914
+
915
+			if (rls_dbf.use_table(rls_db, &rlsubs_table) < 0) 
916
+			{
917
+				LM_ERR("in use_table\n");
918
+				goto done;
919
+			}
904 920
 		
905
-		db_keys[0] =&str_to_tag_col;
906
-		db_vals[0].type = DB1_STR;
907
-		db_vals[0].nul = 0;
908
-		db_vals[0].val.str_val = subs.to_tag;
921
+			db_keys[0] =&str_to_tag_col;
922
+			db_vals[0].type = DB1_STR;
923
+			db_vals[0].nul = 0;
924
+			db_vals[0].val.str_val = subs.to_tag;
909 925
 
910
-		db_keys[1] =&str_callid_col;
911
-		db_vals[1].type = DB1_STR;
912
-		db_vals[1].nul = 0;
913
-		db_vals[1].val.str_val = subs.callid;
926
+			db_keys[1] =&str_callid_col;
927
+			db_vals[1].type = DB1_STR;
928
+			db_vals[1].nul = 0;
929
+			db_vals[1].val.str_val = subs.callid;
914 930
 
915 931
 
916
-		if (rls_dbf.delete(rls_db, db_keys, 0, db_vals, 2) < 0) 
917
-			LM_ERR("cleaning expired messages\n");	
932
+			if (rls_dbf.delete(rls_db, db_keys, 0, db_vals, 2) < 0) 
933
+				LM_ERR("cleaning expired messages\n");	
934
+		}
918 935
 
919 936
 		/* delete from cache table */
920
-		hash_code= core_hash(&subs.callid, &subs.to_tag , hash_size);
921
-
922
-		if(pres_delete_shtable(rls_table,hash_code, subs.to_tag)< 0)
937
+		if (dbmode == RLS_DB_ONLY)
923 938
 		{
924
-			LM_ERR("record not found in hash table\n");
939
+			if (delete_rlsdb(&subs.callid, &subs.to_tag, NULL) < 0 )
940
+			{
941
+				LM_ERR( "unable to delete record from DB\n" );
942
+			}
943
+		}
944
+		else
945
+		{
946
+			hash_code= core_hash(&subs.callid, &subs.to_tag , hash_size);
947
+
948
+			if(pres_delete_shtable(rls_table,hash_code, subs.to_tag)< 0)
949
+			{
950
+				LM_ERR("record not found in hash table\n");
951
+			}
925 952
 		}
926 953
 	}	
927 954
 
... ...
@@ -960,7 +987,7 @@ int process_list_and_exec(xmlNodePtr list_node, str username, str domain,
960 987
 			{
961 988
 				if (rls_integrated_xcap_server == 1
962 989
 					&& (hostname.len == 0
963
-						|| check_self(&hostname, port, PROTO_NONE) == 1))
990
+						|| check_self(&hostname, 0, PROTO_NONE) == 1))
964 991
 				{
965 992
 					LM_DBG("fetching local <resource-list/>\n");
966 993
 					if (rls_get_resource_list(&rl_uri, &username, &domain, &rl_node, &rl_doc)>0)
... ...
@@ -1234,7 +1261,7 @@ int rls_get_resource_list(str *rl_uri, str *username, str *domain,
1234 1261
 	query_vals[n_query_cols].val.str_val = root;
1235 1262
 	n_query_cols++;
1236 1263
 
1237
-	if(rls_dbf.use_table(rls_db, &rls_xcap_table) < 0)
1264
+	if(rls_xcap_dbf.use_table(rls_xcap_db, &rls_xcap_table) < 0)
1238 1265
 	{
1239 1266
 		LM_ERR("in use_table-[table]=%.*s\n",
1240 1267
 			rls_xcap_table.len, rls_xcap_table.s);
... ...
@@ -1243,20 +1270,20 @@ int rls_get_resource_list(str *rl_uri, str *username, str *domain,
1243 1270
 
1244 1271
 	result_cols[xcap_col= n_result_cols++] = &str_doc_col;
1245 1272
 
1246
-	if(rls_dbf.query(rls_db, query_cols, 0, query_vals, result_cols,
1273
+	if(rls_xcap_dbf.query(rls_xcap_db, query_cols, 0, query_vals, result_cols,
1247 1274
 				n_query_cols, n_result_cols, 0, &result)<0)
1248 1275
 	{
1249 1276
 		LM_ERR("failed querying table xcap for document: %.*s\n",
1250 1277
 				root.len, root.s);
1251 1278
 		if(result)
1252
-			rls_dbf.free_result(rls_db, result);
1279
+			rls_xcap_dbf.free_result(rls_xcap_db, result);
1253 1280
 		return -1;
1254 1281
 	}
1255 1282
 
1256 1283
 	if(result->n<=0)
1257 1284
 	{
1258 1285
 		LM_DBG("No rl document found\n");
1259
-		rls_dbf.free_result(rls_db, result);
1286
+		rls_xcap_dbf.free_result(rls_xcap_db, result);
1260 1287
 		return -1;
1261 1288
 	}
1262 1289
 
... ...
@@ -1334,12 +1361,12 @@ int rls_get_resource_list(str *rl_uri, str *username, str *domain,
1334 1361
 		xmlXPathFreeContext(xpathCtx);
1335 1362
 	}
1336 1363
 	
1337
-	rls_dbf.free_result(rls_db, result);
1364
+	rls_xcap_dbf.free_result(rls_xcap_db, result);
1338 1365
 	return 1;
1339 1366
 
1340 1367
 error:
1341 1368
 	if(result!=NULL)
1342
-		rls_dbf.free_result(rls_db, result);
1369
+		rls_xcap_dbf.free_result(rls_xcap_db, result);
1343 1370
 	if(xpathObj!=NULL)
1344 1371
 		xmlXPathFreeObject(xpathObj);
1345 1372
 	
... ...
@@ -93,25 +93,47 @@ void get_dialog_from_did(char* did, subs_t **dialog, unsigned int *hash_code)
93 93
             "resource list Subscribe dialog indentifier(rlsubs did)\n");
94 94
         return;
95 95
 	}
96
-    *hash_code= core_hash(&callid, &to_tag, hash_size);
97
-    
98
-    lock_get(&rls_table[*hash_code].lock);
99
-    s= pres_search_shtable(rls_table,callid,to_tag,from_tag,*hash_code);
100
-    if(s== NULL)
96
+
97
+	if (dbmode == RLS_DB_ONLY)
101 98
 	{
102
-        LM_ERR("record not found in hash_table [rlsubs_did]= %s\n",
103
-                did);
104
-        lock_release(&rls_table[*hash_code].lock);
105
-        return;
99
+		*dialog = get_dialog_rlsdb(callid,to_tag,from_tag);
100
+
101
+		if(*dialog==NULL)
102
+		{
103
+			LM_ERR("record not retrieved from db [rlsubs_did]= %s\n", did);
104
+			return;
105
+		}
106
+	}
107
+	else
108
+	{
109
+		*hash_code= core_hash(&callid, &to_tag, hash_size);
110
+
111
+		lock_get(&rls_table[*hash_code].lock);
112
+		s= pres_search_shtable(rls_table,callid,to_tag,from_tag,*hash_code);
113
+
114
+		if(s== NULL)
115
+		{
116
+			LM_ERR("record not found in hash_table [rlsubs_did]= %s\n",
117
+					did);
118
+			lock_release(&rls_table[*hash_code].lock);
119
+			return;
120
+		}
121
+
122
+		/* save dialog info */
123
+		*dialog= pres_copy_subs(s, PKG_MEM_TYPE);
106 124
 	}
107 125
 
108
-    /* save dialog info */
109
-    *dialog= pres_copy_subs(s, PKG_MEM_TYPE);
110 126
     if(*dialog== NULL)
111 127
 	{
112 128
         LM_ERR("while copying subs_t structure\n");
113 129
 	}
114
-    lock_release(&rls_table[*hash_code].lock);
130
+	else
131
+	{
132
+		dump_dialog( *dialog );
133
+	}
134
+
135
+	if (dbmode != RLS_DB_ONLY)
136
+		lock_release(&rls_table[*hash_code].lock);
115 137
 	
116 138
 }
117 139
 
... ...
@@ -54,24 +54,32 @@
54 54
 #include "rls.h"
55 55
 #include "notify.h"
56 56
 #include "resource_notify.h"
57
+#include "api.h"
57 58
 
58 59
 MODULE_VERSION
59 60
 
60 61
 #define P_TABLE_VERSION 1
61 62
 #define W_TABLE_VERSION 1
63
+#define X_TABLE_VERSION 4
62 64
 
63 65
 /** database connection */
64 66
 db1_con_t *rls_db = NULL;
65 67
 db_func_t rls_dbf;
68
+db1_con_t *rls_xcap_db = NULL;
69
+db_func_t rls_xcap_dbf;
70
+db1_con_t *rls2_db = NULL;
71
+db_func_t rls2_dbf;
66 72
 
67 73
 /** modules variables */
68 74
 str rls_server_address = {0, 0};
75
+int rls_expires_offset=0;
69 76
 int waitn_time = 10;
70 77
 str rlsubs_table = str_init("rls_watchers");
71 78
 str rlpres_table = str_init("rls_presentity");
72 79
 str rls_xcap_table = str_init("xcap");
73 80
 
74 81
 str db_url = str_init(DEFAULT_DB_URL);
82
+str xcap_db_url = str_init("");
75 83
 int hash_size = 512;
76 84
 shtable_t rls_table;
77 85
 int pid;
... ...
@@ -93,6 +101,17 @@ xmlNodeGetNodeContentByName_t XMLNodeGetNodeContentByName;
93 101
 xmlNodeGetAttrContentByName_t XMLNodeGetAttrContentByName;
94 102
 
95 103
 /* functions imported from presence to handle subscribe hash table */
104
+extern shtable_t rls_new_shtable(int hash_size);
105
+extern void rls_destroy_shtable(shtable_t htable, int hash_size);
106
+extern int rls_insert_shtable(shtable_t htable,unsigned int hash_code, subs_t* subs);
107
+extern subs_t* rls_search_shtable(shtable_t htable,str callid,str to_tag,
108
+		str from_tag,unsigned int hash_code);
109
+extern int rls_delete_shtable(shtable_t htable,unsigned int hash_code,str to_tag);
110
+extern int rls_update_shtable(shtable_t htable,unsigned int hash_code, 
111
+		subs_t* subs, int type);
112
+extern void rls_update_db_subs(db1_con_t *db,db_func_t dbf, shtable_t hash_table,
113
+	int htable_size, int no_lock, handle_expired_func_t handle_expired_func);
114
+
96 115
 new_shtable_t pres_new_shtable;
97 116
 insert_shtable_t pres_insert_shtable;
98 117
 search_shtable_t pres_search_shtable;
... ...
@@ -107,6 +126,7 @@ int to_presence_code = 1;
107 126
 int rls_max_expires = 7200;
108 127
 int rls_reload_db_subs = 0;
109 128
 int rls_max_notify_body_len = 0;
129
+int dbmode = 0;
110 130
 
111 131
 /* functions imported from xcap_client module */
112 132
 xcapGetNewDoc_t xcap_GetNewDoc = 0;
... ...
@@ -176,12 +196,15 @@ static cmd_export_t cmds[]=
176 196
 			0, 0, REQUEST_ROUTE},
177 197
 	{"rls_update_subs",       (cmd_function)rls_update_subs,	2,
178 198
 			fixup_update_subs, 0, ANY_ROUTE},
199
+	{"bind_rls",              (cmd_function)bind_rls,		1,
200
+			0, 0, 0},
179 201
 	{0, 0, 0, 0, 0, 0 }
180 202
 };
181 203
 
182 204
 static param_export_t params[]={
183 205
 	{ "server_address",         STR_PARAM,   &rls_server_address.s           },
184 206
 	{ "db_url",                 STR_PARAM,   &db_url.s                       },
207
+	{ "xcap_db_url",            STR_PARAM,   &xcap_db_url.s                  },
185 208
 	{ "rlsubs_table",           STR_PARAM,   &rlsubs_table.s                 },
186 209
 	{ "rlpres_table",           STR_PARAM,   &rlpres_table.s                 },
187 210
 	{ "xcap_table",             STR_PARAM,   &rls_xcap_table.s               },
... ...
@@ -196,6 +219,8 @@ static param_export_t params[]={
196 219
 	{ "outbound_proxy",         STR_PARAM,   &rls_outbound_proxy.s           },
197 220
 	{ "reload_db_subs",         INT_PARAM,   &rls_reload_db_subs             },
198 221
 	{ "max_notify_body_length", INT_PARAM,	 &rls_max_notify_body_len	     },
222
+	{ "db_mode",                INT_PARAM,	 &dbmode			 },
223
+	{ "expires_offset",         INT_PARAM,	 &rls_expires_offset		 },
199 224
 	{0,                         0,           0                               }
200 225
 };
201 226
 
... ...
@@ -232,6 +257,12 @@ static int mod_init(void)
232 257
 
233 258
 	LM_DBG("start\n");
234 259
 
260
+	if (dbmode <RLS_DB_DEFAULT || dbmode > RLS_DB_ONLY)
261
+	{
262
+		LM_ERR( "Invalid dbmode-set to default mode\n" );
263
+		dbmode = 0;
264
+	}
265
+
235 266
 	if(rls_server_address.s==NULL)
236 267
 	{
237 268
 		LM_ERR("server_address parameter not set in configuration file\n");
... ...
@@ -304,14 +335,35 @@ static int mod_init(void)
304 335
 	pres_contains_event = pres.contains_event;
305 336
 	pres_search_event   = pres.search_event;
306 337
 	pres_get_ev_list    = pres.get_event_list;
307
-	pres_new_shtable    = pres.new_shtable;
308
-	pres_destroy_shtable= pres.destroy_shtable;
309
-	pres_insert_shtable = pres.insert_shtable;
310
-	pres_delete_shtable = pres.delete_shtable;
311
-	pres_update_shtable = pres.update_shtable;
312
-	pres_search_shtable = pres.search_shtable;
338
+
339
+	if (rls_expires_offset < 0 ) 
340
+	{
341
+		LM_ERR( "Negative expires_offset, defaulted to zero\n" );
342
+		rls_expires_offset = 0; 
343
+	}
344
+
345
+	if (dbmode == RLS_DB_ONLY)
346
+	{
347
+		pres_new_shtable    = rls_new_shtable;
348
+		pres_destroy_shtable= rls_destroy_shtable;
349
+		pres_insert_shtable = rls_insert_shtable;
350
+		pres_delete_shtable = rls_delete_shtable;
351
+		pres_update_shtable = rls_update_shtable;
352
+		pres_search_shtable = rls_search_shtable;
353
+		pres_update_db_subs = rls_update_db_subs;
354
+	}
355
+	else
356
+	{
357
+		pres_new_shtable    = pres.new_shtable;
358
+		pres_destroy_shtable= pres.destroy_shtable;
359
+		pres_insert_shtable = pres.insert_shtable;
360
+		pres_delete_shtable = pres.delete_shtable;
361
+		pres_update_shtable = pres.update_shtable;
362
+		pres_search_shtable = pres.search_shtable;
363
+		pres_update_db_subs = pres.update_db_subs;
364
+	}
365
+
313 366
 	pres_copy_subs      = pres.mem_copy_subs;
314
-	pres_update_db_subs = pres.update_db_subs;
315 367
 	pres_extract_sdialog_info= pres.extract_sdialog_info;
316 368
 
317 369
 	if(!pres_contains_event || !pres_get_ev_list || !pres_new_shtable ||
... ...
@@ -328,57 +380,112 @@ static int mod_init(void)
328 380
 	rls_xcap_table.len= strlen(rls_xcap_table.s);
329 381
 	db_url.len = db_url.s ? strlen(db_url.s) : 0;
330 382
 	LM_DBG("db_url=%s/%d/%p\n", ZSW(db_url.s), db_url.len, db_url.s);
383
+
384
+	xcap_db_url.len = xcap_db_url.s ? strlen(xcap_db_url.s) : 0;
385
+
386
+	if(xcap_db_url.len==0)
387
+	{
388
+		xcap_db_url.s = db_url.s;
389
+		xcap_db_url.len = db_url.len;
390
+	}
391
+
392
+	LM_DBG("db_url=%s/%d/%p\n", ZSW(xcap_db_url.s), xcap_db_url.len, xcap_db_url.s);
331 393
 	
332 394
 	/* binding to mysql module  */
395
+
396
+	/* rls2_db handle is to ensure that there are no unwanted interactions
397
+	   between the original database reads and the DB_ONLY mode stuff */
398
+
399
+	if (db_bind_mod(&db_url, &rls2_dbf))
400
+	{
401
+		LM_ERR("Database module not found\n");
402
+		return -1;
403
+	}
404
+
333 405
 	if (db_bind_mod(&db_url, &rls_dbf))
334 406
 	{
335 407
 		LM_ERR("Database module not found\n");
336 408
 		return -1;
337 409
 	}
338
-	
410
+
411
+	if (db_bind_mod(&xcap_db_url, &rls_xcap_dbf))
412
+	{
413
+		LM_ERR("Database module not found\n");
414
+		return -1;
415
+	}
416
+
339 417
 	if (!DB_CAPABILITY(rls_dbf, DB_CAP_ALL)) {
340 418
 		LM_ERR("Database module does not implement all functions"
341 419
 				" needed by the module\n");
342 420
 		return -1;
343 421
 	}
344 422
 
423
+	if (!DB_CAPABILITY(rls_xcap_dbf, DB_CAP_ALL)) {
424
+		LM_ERR("Database module does not implement all functions"
425
+				" needed by the module\n");
426
+		return -1;
427
+	}
428
+
345 429
 	rls_db = rls_dbf.init(&db_url);
346 430
 	if (!rls_db)
347 431
 	{
348 432
 		LM_ERR("while connecting database\n");
349 433
 		return -1;
350 434
 	}
435
+
436
+	rls_xcap_db = rls_xcap_dbf.init(&xcap_db_url);
437
+	if (!rls_xcap_db)
438
+	{
439
+		LM_ERR("while connecting database\n");
440
+		return -1;
441
+	}
442
+
351 443
 	/* verify table version */
352 444
 	if((db_check_table_version(&rls_dbf, rls_db, &rlsubs_table, W_TABLE_VERSION) < 0) ||
353 445
 		(db_check_table_version(&rls_dbf, rls_db, &rlpres_table, P_TABLE_VERSION) < 0)) {
354 446
 			LM_ERR("error during table version check.\n");
355 447
 			return -1;
356 448
 	}
357
-	
358
-	if(hash_size<=1)
359
-		hash_size= 512;
360
-	else
361
-		hash_size = 1<<hash_size;
362 449
 
363
-	rls_table= pres_new_shtable(hash_size);
364
-	if(rls_table== NULL)
450
+	/* verify table version */
451
+	if(db_check_table_version(&rls_xcap_dbf, rls_xcap_db, &rls_xcap_table, X_TABLE_VERSION) < 0)
365 452
 	{
366
-		LM_ERR("while creating new hash table\n");
367
-		return -1;
453
+			LM_ERR("error during table version check.\n");
454
+			return -1;
368 455
 	}
369
-	if(rls_reload_db_subs!=0)
456
+
457
+	if (dbmode != RLS_DB_ONLY)
370 458
 	{
371
-		if(rls_restore_db_subs()< 0)
459
+		if(hash_size<=1)
460
+			hash_size= 512;
461
+		else
462
+			hash_size = 1<<hash_size;
463
+
464
+		rls_table= pres_new_shtable(hash_size);
465
+		if(rls_table== NULL)
372 466
 		{
373
-			LM_ERR("while restoring rl watchers table\n");
467
+			LM_ERR("while creating new hash table\n");
374 468
 			return -1;
375 469
 		}
470
+		if(rls_reload_db_subs!=0)
471
+		{
472
+			if(rls_restore_db_subs()< 0)
473
+			{
474
+				LM_ERR("while restoring rl watchers table\n");
475
+				return -1;
476
+			}
477
+		}
376 478
 	}
377 479
 
378 480
 	if(rls_db)
379 481
 		rls_dbf.close(rls_db);
380 482
 	rls_db = NULL;
381 483
 
484
+	if(rls_xcap_db)
485
+		rls_xcap_dbf.close(rls_xcap_db);
486
+	rls_xcap_db = NULL;
487
+
488
+
382 489
 	if(waitn_time<= 0)
383 490
 		waitn_time= 5;
384 491
 	
... ...
@@ -460,10 +567,13 @@ static int mod_init(void)
460 567
 	}
461 568
 	register_timer(timer_send_notify,0, waitn_time);
462 569
 	
463
-	register_timer(rls_presentity_clean, 0, clean_period);
464
-	
465
-	register_timer(rlsubs_table_update, 0, clean_period);
570
+	if (clean_period > 0)
571
+	{
572
+		register_timer(rls_presentity_clean, 0, clean_period);
466 573
 	
574
+		register_timer(rlsubs_table_update, 0, clean_period);
575
+	}
576
+
467 577
 	return 0;
468 578
 }
469 579
 
... ...
@@ -476,6 +586,48 @@ static int child_init(int rank)
476 586
 		return 0; /* do nothing for the main process */
477 587
 
478 588
 	LM_DBG("child [%d]  pid [%d]\n", rank, getpid());
589
+
590
+	if (rls2_dbf.init==0)
591
+	{
592
+		LM_CRIT("database not bound\n");
593
+		return -1;
594
+	}
595
+	rls2_db = rls2_dbf.init(&db_url);
596
+	if (!rls2_db)
597
+	{
598
+		LM_ERR("child %d: Error while connecting database\n",
599
+				rank);
600
+		return -1;
601
+	}
602
+	if (rls2_dbf.use_table(rls2_db, &rlsubs_table) < 0)  
603
+	{
604
+		LM_ERR("child %d: Error in use_table rlsubs_table\n", rank);
605
+		return -1;
606
+	}
607
+
608
+	if (rls_xcap_dbf.init==0)
609
+	{
610
+		LM_CRIT("database not bound\n");
611
+		return -1;
612
+	}
613
+
614
+	rls_xcap_db = rls_xcap_dbf.init(&xcap_db_url);
615
+	if (!rls_xcap_db)
616
+	{
617
+		LM_ERR("child %d: Error while connecting database\n", rank);
618
+		return -1;
619
+	}
620
+	else
621
+	{
622
+		if (rls_xcap_dbf.use_table(rls_xcap_db, &rls_xcap_table) < 0)  
623
+		{
624
+			LM_ERR("child %d: Error in use_table rls_xcap_table\n", rank);
625
+			return -1;
626
+		}
627
+
628
+		LM_DBG("child %d: Database connection opened successfully\n", rank);
629
+	}
630
+
479 631
 	if (rls_dbf.init==0)
480 632
 	{
481 633
 		LM_CRIT("database not bound\n");
... ...
@@ -523,6 +675,9 @@ static void destroy(void)
523 675
 	}
524 676
 	if(rls_db && rls_dbf.close)
525 677
 		rls_dbf.close(rls_db);
678
+
679
+	if(rls2_db && rls2_dbf.close)
680
+		rls2_dbf.close(rls2_db);
526 681
 }
527 682
 
528 683
 int handle_expired_record(subs_t* s)
... ...
@@ -547,6 +702,8 @@ void rlsubs_table_update(unsigned int ticks,void *param)
547 702
 {
548 703
 	int no_lock= 0;
549 704
 
705
+	if (dbmode==RLS_DB_ONLY) { delete_expired_subs_rlsdb(); return; }
706
+
550 707
 	if(ticks== 0 && param == NULL)
551 708
 		no_lock= 1;
552 709
 	
... ...
@@ -755,3 +912,16 @@ int add_rls_event(modparam_t type, void* val)
755 912
 	return 0;
756 913
 
757 914
 }
915
+
916
+int bind_rls(struct rls_binds *pxb)
917
+{
918
+		if (pxb == NULL)
919
+		{
920
+				LM_WARN("bind_rls: Cannot load rls API into a NULL pointer\n");
921
+				return -1;
922
+		}
923
+
924
+		pxb->rls_handle_subscribe = rls_handle_subscribe;
925
+		pxb->rls_handle_notify = rls_handle_notify;
926
+		return 0;
927
+}
... ...
@@ -40,6 +40,10 @@
40 40
 #include "../../lib/srdb1/db_con.h"
41 41
 #include "../../lib/srdb1/db.h"
42 42
 
43
+#define RLS_DB_DEFAULT 0
44
+#define RLS_DB_RESERVED 1
45
+#define RLS_DB_ONLY 2
46
+
43 47
 #define NO_UPDATE_TYPE     -1 
44 48
 #define UPDATED_TYPE        1 
45 49
 
... ...
@@ -79,7 +83,7 @@ typedef struct rls_resource
79 83
 	/* the last 2 parameters say if a query in database is needed */
80 84
 }rls_res_t;
81 85
 
82
-
86
+extern int dbmode;
83 87
 extern char* xcap_root;
84 88
 extern unsigned int xcap_port;
85 89
 extern str rls_server_address;
... ...
@@ -97,10 +101,13 @@ extern int rls_events;
97 101
 extern int to_presence_code;
98 102
 extern str rls_outbound_proxy;
99 103
 extern int rls_max_notify_body_len;
104
+extern int rls_expires_offset;
100 105
 
101 106
 /* database connection */
102 107
 extern db1_con_t *rls_db;
103 108
 extern db_func_t rls_dbf;
109
+extern db1_con_t *rls_xcap_db;
110
+extern db_func_t rls_xcap_dbf;
104 111
 
105 112
 extern struct tm_binds tmb;
106 113
 extern sl_api_t slb;
... ...
@@ -137,6 +144,17 @@ extern xcap_nodeSel_add_step_t xcap_AddStep;
137 144
 extern xcap_nodeSel_add_terminal_t xcap_AddTerminal;
138 145
 extern xcap_nodeSel_free_t xcap_FreeNodeSel;
139 146
 
147
+/* rlsdb functions*/
148
+int delete_expired_subs_rlsdb( void );
149
+void dump_dialog( subs_t *s );
150
+extern int delete_rlsdb( str *callid, str *to_tag, str *from_tag );
151
+extern int update_rlsdb( subs_t *s, int type );
152
+extern int update_subs_rlsdb( subs_t *s );
153
+extern int insert_rlsdb( subs_t *s );
154
+extern int matches_in_rlsdb( str callid, str to_tag, str from_tag );
155
+extern int update_all_subs_rlsdb( str *from_user, str *from_domain, str *evt );
156
+subs_t *get_dialog_rlsdb( str callid, str to_tag, str from_tag );
157
+
140 158
 extern str str_rlsubs_did_col;
141 159
 extern str str_resource_uri_col;
142 160
 extern str str_updated_col;
143 161
new file mode 100644
... ...
@@ -0,0 +1,1220 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * rls db - RLS database support 
5
+ *
6
+ * Copyright (C) 2011 Crocodile RCS Ltd
7
+ *
8
+ * This file is part of Kamailio, a free SIP server.
9
+ *
10
+ * Kamailio is free software; you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License as published by
12
+ * the Free Software Foundation; either version 2 of the License, or
13
+ * (at your option) any later version
14
+ *
15
+ * Kamailio is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
+ * GNU General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU General Public License 
21
+ * along with this program; if not, write to the Free Software 
22
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
+ */
24
+
25
+
26
+#include <stdio.h>
27
+#include <stdlib.h>
28
+#include <string.h>
29
+
30
+#include "../../mem/mem.h"
31
+#include "../../mem/shm_mem.h"
32
+#include "../../dprint.h"
33
+#include "../../lib/srdb1/db.h"
34
+#include "../../parser/msg_parser.h"
35
+#include "../../parser/parse_from.h"
36
+
37
+#include "rls.h"
38
+
39
+#define CONT_COPYDB(buf, dest, source)\
40
+	do{ \
41
+	dest.s= (char*)buf+ size;\
42
+	memcpy(dest.s, source, strlen(source));\
43
+	dest.len= strlen(source);\
44
+	size+= strlen(source); \
45
+	} while(0);
46
+
47
+/* database connection */
48
+extern db1_con_t *rls2_db;
49
+extern db_func_t rls2_dbf;
50
+
51
+extern void update_a_sub(subs_t *subs_copy );
52
+
53
+static int rlsdb_debug=0;
54
+
55
+/******************************************************************************/
56
+
57
+shtable_t rls_new_shtable(int hash_size)
58
+{
59
+  LM_ERR( "rls_new_shtable shouldn't be called in RLS_DB_ONLY mode\n" );
60
+  return(NULL);
61
+}
62
+
63
+/******************************************************************************/
64
+
65
+void rls_destroy_shtable(shtable_t htable, int hash_size)
66
+{
67
+  LM_ERR( "rls_destroy_shtable shouldn't be called in RLS_DB_ONLY mode\n" );
68
+}
69
+
70
+/******************************************************************************/
71
+
72
+int rls_insert_shtable(shtable_t htable,unsigned int hash_code, subs_t* subs)
73
+{