-
Notifications
You must be signed in to change notification settings - Fork 676
Expand file tree
/
Copy pathusrloc.h
More file actions
464 lines (419 loc) · 16.3 KB
/
Copy pathusrloc.h
File metadata and controls
464 lines (419 loc) · 16.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
/*
* Convenience usrloc header file
*
* Copyright (C) 2001-2003 FhG Fokus
*
* This file is part of opensips, a free SIP server.
*
* opensips is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* opensips is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*! \file
* \brief USRLOC - Convenience usrloc header file
* \ingroup usrloc
*/
#ifndef USRLOC_H
#define USRLOC_H
#include "dlist.h"
#include "udomain.h"
#include "urecord.h"
#include "ucontact.h"
#include "ul_callback.h"
#include "ul_dbg.h"
typedef enum ul_cluster_mode {
CM_NONE,
CM_FEDERATION,
CM_FEDERATION_CACHEDB,
CM_FULL_SHARING,
CM_FULL_SHARING_CACHEDB,
CM_SQL_ONLY,
} ul_cluster_mode_t;
typedef struct usrloc_api {
int use_domain;
enum ul_cluster_mode cluster_mode;
/* whether the user location caches contacts in OpenSIPS memory */
int (*have_mem_storage) (void);
/* whether the user location makes use of contact ownership tags */
int (*tags_in_use) (void);
/* the NAT branch flag, as bitmask */
unsigned int nat_flag;
/**
* Register a new usrloc domain. If the domain already exists, a pointer
* to an existing structure will be returned.
* NOTE: may only be called before forking! (e.g., during mod_init())
*
* @name: name of the new domain (if using a DB, it is also the table name)
* @d: output variable holding the domain
*
* Return: 0 (success), negative otherwise
*/
int (*register_udomain) (const char *name, udomain_t **d);
/**
* Lock/Unlock the hash table entry of the given Address-of-Record.
* NOTE: you MUST always lock an AoR before using any AoR or contact
* manipulation functions of this API.
*
* @d: the usrloc domain to use
* @aor: the AoR to grab/release the entry for
*/
void (*lock_udomain) (udomain_t *d, str *aor);
void (*unlock_udomain) (udomain_t *d, str *aor);
/**
* Fetch a given AoR from an usrloc domain.
* NOTE: remember to @release_urecord() when you are done with it!
*
* @d: the domain to search within
* @aor: the AoR to fetch
* @r: will hold the returned object if found, NULL otherwise
*
* Return: 0 (found), 1 (not found) otherwise
*/
int (*get_urecord) (udomain_t *d, str *aor, struct urecord **r);
/**
* Fetch a given AoR from an usrloc domain, across multiple locations.
* Thus, this function is only relevant when using
* cluster_mode == CM_FEDERATION_CACHEDB. The function will return success
* if the AoR exists in at least one location.
*
* @d: the domain to search within
* @aor: the AoR to fetch
* @r: will hold the returned object if found, NULL otherwise
*
* Return: 0 (found), 1 (not found) otherwise
*/
int (*get_global_urecord) (udomain_t *d, str *aor, struct urecord **r);
/**
* Release an (urecord_t) object previously obtained through either
* @get_urecord or @get_global_urecord.
*
* @r: the usrloc record to release
* @skip_replication: set to true in order to avoid replicating an AoR
* deletion event, if any, to neighboring cluster nodes
*/
void (*release_urecord) (urecord_t *r, char skip_replication);
/**
* Create and insert a new Address-of-Record into the given domain.
* NOTE: will leak shared memory if the record already exists! Use
* @get_urecord accordingly beforehand to prevent this.
*
* @d: the domain to insert the record into
* @aor: the AoR to insert
* @r: will hold the newly created object
* @skip_replication: set to true in order to avoid replicating an AoR
* insertion event to neighboring cluster nodes
* @pre_replicate_cb: optional callback fired after the urecord lives in
* memory but before it is replicated; use it to attach
* record-level kv_storage that must reach peers
* @pre_replicate_info: opaque context handed to @pre_replicate_cb
*
* Return: 0 (success), negative otherwise
*/
int (*insert_urecord) (udomain_t *d, str *aor, struct urecord **r,
char skip_replication,
ur_insert_pre_repl_cb_f pre_replicate_cb,
void *pre_replicate_info);
/**
* Fetch a key from record-level storage.
* NOTE: remember to lock the urecord beforehand.
*
* @r: the record to search into
* @key: the key to locate
*
* Return: NULL on error/key not found, value pointer otherwise
*/
int_str_t *(*get_urecord_key) (urecord_t *r, const str *key);
/**
* Create or re-assign a key-value pair within record-level storage.
* NOTES:
* - remember to lock the urecord beforehand
* - both @key and @val will be duplicated in shared memory
*
* @r: the record to search into
* @key: the key to locate
* @val: the value to set
*
* Return: NULL on error, new value pointer otherwise
*/
int_str_t *(*put_urecord_key) (urecord_t *r, const str *key,
const int_str_t *val);
/**
* Delete a given AoR from an usrloc domain, along with all of its
* contacts.
*
* @d: the domain to search within
* @aor: the AoR to delete
* @r: optional, if available -- the exact object to delete
* @skip_replication: set to true in order to avoid replicating deletion
* events to neighboring cluster nodes for both contact
* and AoR deletions
*
* Return: 0 (success), negative otherwise
*/
int (*delete_urecord) (udomain_t *d, str *aor, struct urecord *r,
char skip_replication);
/**
* Match a contact against a list of contacts stored in an usrloc record.
*
* @r: the usrloc record to search for the contact
* @ct_uri: the contact URI to search
* @callid: the SIP Call-ID of the pending REGISTER message
* @cseq: the SIP CSeq of the pending REGISTER message
* @match: how to match the contact against existing bindings
* @c: will hold the returned contact if found or NULL
*
* Return:
* 0 - contact found and returned in @c
* 1 - contact not found
* -1 - contact found, however the given @cseq is too old and you
* should ignore this REGISTER
* -2 - contact found, however the given @cseq is equal to the existing
* one, so you should ignore this REGISTER (is it a retransmission?)
*/
int (*get_ucontact) (urecord_t *r, str *ct_uri, str *callid, int cseq,
const struct ct_match *match, ucontact_t **c);
/**
* Fetch a ucontact from an usrloc domain using a contact ID.
* NOTE: on success, the urecord *lock will be grabbed*!
* Remember to @release_urecord, followed by @unlock_udomain!
*
* @d: the domain to search within
* @id: the contact ID, a 64-bit unsigned integer
* @r: will hold the contact's usrloc record, if found
*
* Return:
* NULL, if contact not found
* pointer to the contact, if found
*/
ucontact_t *(*get_ucontact_from_id) (udomain_t *d,
ucontact_id id, urecord_t **r);
/**
* Create and add a new contact to the list of contacts in @r. If
* @desc_time_order is on, the contact will be simply appended at the head
* of the list (most recent), otherwise in descending q-value order.
*
* @r: the usrloc record of the contact
* @ct_uri: the SIP URI of the contact
* @ci: various info pertaining to the contact, extract from the REGISTER
* message (and not only!)
* @match: Required if @skip_replication is false, in order to instruct
* the replicas on how to match this contact
* @skip_replication: set to true in order to avoid replicating an "insert"
* event to neighboring cluster nodes
* @c: will hold the output contact, once created
*
* Return: 0 (success), negative otherwise
*/
int (*insert_ucontact) (urecord_t *r, str *ct_uri, ucontact_info_t *ci,
const struct ct_match *match, char skip_replication,
ucontact_t **c);
/**
* Update the info of an existing usrloc contact, possibly on a re-REGISTER
*
* @r: the usrloc record of the contact
* @c: the usrloc contact to update
* @ci: various info pertaining to the contact to update
* @match: Required if @skip_replication is false, in order to instruct
* the replicas on how to match this contact
* @skip_replication: set to true in order to avoid replicating an "update"
* event to neighboring cluster nodes
*
* Return: 0 (success), negative otherwise
*/
int (*update_ucontact) (urecord_t *r, ucontact_t *c, ucontact_info_t *ci,
const struct ct_match *match, char skip_replication);
/**
* Fetch a key from contact-level storage.
* NOTE: remember to lock the urecord beforehand.
*
* @c: the usrloc contact to search into
* @key: the key to locate
*
* Return: NULL on error/key not found, value pointer otherwise
*/
int_str_t *(*get_ucontact_key) (ucontact_t *c, const str *key);
/**
* Create or re-assign a key-value pair within contact-level storage.
* NOTES:
* - remember to lock the urecord beforehand
* - both @key and @val will be duplicated in shared memory
*
* @c: the usrloc contact to search into
* @key: the key to locate
* @val: the value to set
*
* Return: NULL on error, new value pointer otherwise
*/
int_str_t *(*put_ucontact_key) (ucontact_t *c, const str *key,
const int_str_t *val);
/**
* Delete a contact from a given usrloc record.
*
* @r: the usrloc record
* @c: the usrloc contact to delete
* @skip_replication: set to true in order to avoid replicating a "delete"
* event to neighboring cluster nodes
*
* Return: 0 (success), negative otherwise
*/
int (*delete_ucontact) (urecord_t *r, ucontact_t *c,
const struct ct_match *match, char skip_replication);
/**
* Delete a contact from a given usrloc domain, using its hash table or
* SIP coordinates.
*
* @d: the usrloc domain to search within
* @coords: the contact ID or SIP coordinates of the contact
* (see @ucontact_coords for more info)
* @skip_replication: set to true in order to avoid replicating a "delete"
* event to neighboring cluster nodes
*
* Return: 0 (success), negative otherwise
*/
int (*delete_ucontact_from_coords) (udomain_t *d, ucontact_coords coords,
char skip_replication);
/**
* Compare @ucontact_coords structs @a and @b.
*
* Return: 0 if equal, -1 otherwise
*/
int (*ucontact_coords_cmp) (ucontact_coords a, ucontact_coords b);
/**
* Free an @ucontact_coords object.
*/
void (*free_ucontact_coords) (ucontact_coords coords);
/**
* Check if an ucontact is logically owned by the current OpenSIPS node.
* Always returns true in single node setups or if a contact does not have
* an ownership tag attached.
*
* Return: 1 (true), 0 (false)
*/
int (*is_my_ucontact) (ucontact_t *c);
/**
* Generate the next contact ID of a given record. Returns a different
* contact ID on each new call, rotating across CLABEL_MASK values.
*
* @r: the usrloc record
*
* Return: the next contact ID
*/
uint64_t (*next_contact_id) (urecord_t *r);
/**
* Update the SIP pinging latency of a contact, i.e. the round-trip delay
* of pinging a contact using a SIP OPTIONS message.
*
* @d: the usrloc domain to update
* @coords: the SIP coordinates of the contact
* @sipping_latency: new latency value, in microseconds
*
* Return: 0 (success), negative otherwise
*/
int (*update_sipping_latency) (udomain_t *d, ucontact_coords coords,
int sipping_latency);
/**
* Raise an async registration refresh event for an usrloc contact
*
* @ct: the usrloc contact
* @reason: short text denoting the reason for the refresh
* @req_callid: Call-ID of the pending SIP request or NULL if not available
*/
void (*raise_ev_ct_refresh) (const ucontact_t *ct, const str *reason,
const str *req_callid);
/**
* Easily iterate through all currently registered domains.
* @d: the last fetched domain. Use a NULL value to fetch the 1st domain.
*
* Return: the next domain or NULL if the end of list end has been reached.
*/
udomain_t *(*get_next_udomain) (udomain_t *d);
/**
* Low-level functions to lock/unlock a hash table bucket on a given domain
* @d: the domain to use
* @slot: the index of the bucket, must be less than @d->size
*/
void (*lock_ulslot) (udomain_t *d, int slot);
void (*unlock_ulslot) (udomain_t *d, int slot);
/**
* Return all contacts for all currently registered users in the given
* domain. The function expects a buffer of sufficient length to fit all
* contacts. If the buffer is exhausted, the function returns the
* estimated amount of additional space needed. In this case, the caller
* is expected to repeat the call using this value as the hint.
*
* @d: the usrloc domain to search within
* @buf: the input buffer
* @buf_len: the length of the buffer
* @flags: flag bitmask to be used as a filter (use 0 to skip)
* @part_idx / @part_max: partition the contact space. E.g.:
* * to only grab the top 25% of contacts, use: "0 / 4"
* * to grab all contacts, use: "0 / 1"
* @pack_coords: Set to 1 to include the contact coords in the buffer,
* otherwise 0. See @ucontact_coords for more info.
*
* The contact information is packed into the buffer as follows:
*
* +=======+======+=========+=======+=============+======+========+=======+
* |int |char[]|int |char[] |socket_info *|uint |proxy_l |uint64 |
* +=======+======+=========+=======+=============+======+========+=======+
* |ct1.len|ct1.s |path1.len|path1.s|sock1 |flags1|nx_hop1 |coords1|
* +-------+------+---------+-------+-------------+------+--------+-------+
* |ct2.len|ct2.s |path2.len|path2.s|sock2 |flags2|nx_hop2 |coords2|
* +-------+------+---------+-------+-------------+------+--------+-------+
* | ... | ... | ... | ... | ... | ... | ... | ... |
* +-------+------+---------+-------+-------------+------+--------+-------+
* |ctN.len|ctN.s |pathN.len|pathN.s|sockN |flagsN|nx_hopN |coordsN|
* +-------+------+---------+-------+-------------+------+--------+-------+
* |0000000|
* +-------+
*/
int (*get_domain_ucontacts) (udomain_t *d, void *buf, int buf_len,
unsigned int flags, unsigned int part_idx,
unsigned int part_max, int pack_coords);
/**
* Similar to @get_domain_ucontacts, except it works for all current usrloc
* domains, with the contacts of each domain being merged together, without
* the ability to discern the domain of a given contact anymore.
*/
int (*get_all_ucontacts) (void *buf, int buf_len, unsigned int flags,
unsigned int part_idx, unsigned int part_max,
int pack_coords);
/**
* Subscribe to various user location create/update/delete/expire events
* concerning records (AoRs) and contacts.
*
* @types: bitmask of callback types to register the @cb callback for
* @cb: The registered callback function. Explanation of its arguments:
* - @binding: depending on the callback type, you should cast it to
* either (ucontact_t *) or (urecord_t *)
* - @type: type of the invoked callback (e.g. UL_CONTACT_EXPIRE)
*
* Return: 0 (success), negative otherwise
*/
int (*register_ulcb) (ul_cb_type types,
void (*cb) (void *binding, ul_cb_type type, ul_cb_extra *extra));
} usrloc_api_t;
typedef int (*bind_usrloc_t)(usrloc_api_t* api);
static inline int load_ul_api(usrloc_api_t *ul)
{
bind_usrloc_t bind_usrloc;
bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 0);
if (!bind_usrloc) {
LM_ERR("can't bind usrloc\n");
return -1;
}
if (bind_usrloc(ul) < 0)
return -1;
return 0;
}
#endif /* USRLOC_H */