Skip to content

Commit 669a9b3

Browse files
committed
[pua] added list_presentities and list_subscription MI function
to list the published presentities or the subscriptions done via the pua module. Filters for presentity URI and/or event are available
1 parent 9556ed5 commit 669a9b3

2 files changed

Lines changed: 231 additions & 1 deletion

File tree

‎modules/pua/README.md‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,59 @@ if($rm=="NOTIFY")
294294
```
295295

296296

297+
### Exported MI Functions
298+
299+
#### pua:list_presentities
300+
301+
Lists only the publish presentity records in the local PUA hash table.
302+
Subscription records are excluded. With no parameters, all publish
303+
records are returned. The optional filters may be used independently or
304+
together:
305+
306+
- `pres_uri`: exact presentity URI to match.
307+
- `event`: registered event name to match, such as `presence` or `dialog`.
308+
An unknown event returns a 400 error.
309+
310+
The result is an array containing the following fields of
311+
each publish record: `pres_uri`, `event`,
312+
`expires`, `desired_expires`, `flag`, `db_flag`, `ua_flag`, `etag`,
313+
`tuple_id`, `waiting_reply` and `pending_publ`. The `etag` and `sharing_tag`
314+
fields are included only when set. Expiration values are Unix
315+
timestamps. Each pending publication contains `content_type`, `body`,
316+
`extra_headers` and `expires` (the requested lifetime in seconds).
317+
Internal identifiers, pointers and subscribe fields are omitted. No matches returns
318+
an empty array.
319+
320+
```shell
321+
opensips-cli -x mi pua:list_presentities
322+
opensips-cli -x mi pua:list_presentities pres_uri=sip:alice@example.com
323+
opensips-cli -x mi pua:list_presentities event=presence
324+
opensips-cli -x mi pua:list_presentities pres_uri=sip:alice@example.com event=presence
325+
```
326+
327+
#### pua:list_subscription
328+
329+
Lists only the subscription records in the local PUA hash table. With no
330+
parameters, all subscription records are returned. The optional `pres_uri`
331+
and `event` filters work independently or together, as for
332+
`pua:list_presentities`. An unknown event returns a 400 error; no matches
333+
returns an empty array.
334+
335+
Each record contains the common fields `pres_uri`, `event`, `expires`,
336+
`desired_expires`, `flag`, `db_flag` and `ua_flag`, plus the subscription
337+
fields `to_uri`, `watcher_uri`, `call_id`, `to_tag`, `from_tag`, `cseq`,
338+
`version`, `watcher_count`, `extra_headers`, `record_route`,
339+
`remote_contact` and `contact`. The `sharing_tag` and `outbound_proxy`
340+
fields are included only when set. Expiration values are Unix timestamps.
341+
Internal identifiers, pointers and publish fields are omitted.
342+
343+
```shell
344+
opensips-cli -x mi pua:list_subscription
345+
opensips-cli -x mi pua:list_subscription pres_uri=sip:alice@example.com
346+
opensips-cli -x mi pua:list_subscription event=presence
347+
opensips-cli -x mi pua:list_subscription pres_uri=sip:alice@example.com event=presence
348+
```
349+
297350
### Installation
298351

299352

‎modules/pua/pua.c‎

Lines changed: 178 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "../../mem/mem.h"
4141
#include "../../pt.h"
4242
#include "../../db/db.h"
43+
#include "../../mi/mi.h"
4344
#include "../tm/tm_load.h"
4445
#include "../presence/hash.h"
4546
#include "pua.h"
@@ -101,6 +102,28 @@ static void destroy(void);
101102
static int update_pua(ua_pres_t* p, unsigned int hash_code, unsigned int final);
102103
static void db_update(unsigned int ticks,void *param);
103104
static void hashT_clean(unsigned int ticks,void *param);
105+
static mi_response_t *mi_list_presentities(const mi_params_t *params,
106+
struct mi_handler *async_hdl);
107+
static mi_response_t *mi_list_subscription(const mi_params_t *params,
108+
struct mi_handler *async_hdl);
109+
110+
static const mi_export_t mi_cmds[] = {
111+
{ "list_presentities", 0,0,0, {
112+
{mi_list_presentities, {0}},
113+
{mi_list_presentities, {"pres_uri", 0}},
114+
{mi_list_presentities, {"event", 0}},
115+
{mi_list_presentities, {"pres_uri", "event", 0}},
116+
{EMPTY_MI_RECIPE}}, {0}
117+
},
118+
{ "list_subscription", 0,0,0, {
119+
{mi_list_subscription, {0}},
120+
{mi_list_subscription, {"pres_uri", 0}},
121+
{mi_list_subscription, {"event", 0}},
122+
{mi_list_subscription, {"pres_uri", "event", 0}},
123+
{EMPTY_MI_RECIPE}}, {0}
124+
},
125+
{EMPTY_MI_EXPORT}
126+
};
104127

105128
static const cmd_export_t cmds[]={
106129
{"pua_update_contact",(cmd_function)update_contact, {{0,0,0}},
@@ -144,7 +167,7 @@ struct module_exports exports= {
144167
0, /* exported async functions */
145168
params, /* exported parameters */
146169
0, /* exported statistics */
147-
0, /* exported MI functions */
170+
mi_cmds, /* exported MI functions */
148171
0, /* exported pseudo-variables */
149172
0, /* exported transformations */
150173
0, /* extra processes */
@@ -156,6 +179,160 @@ struct module_exports exports= {
156179
0 /* reload confirm function */
157180
};
158181

182+
static int mi_print_common(mi_item_t *item, ua_pres_t *p)
183+
{
184+
pua_event_t *event;
185+
186+
event = get_event(p->event);
187+
if (add_mi_string(item, MI_SSTR("pres_uri"),
188+
p->pres_uri->s, p->pres_uri->len) < 0 ||
189+
(event ? add_mi_string(item, MI_SSTR("event"),
190+
event->name.s, event->name.len) :
191+
add_mi_number(item, MI_SSTR("event"), p->event)) < 0 ||
192+
add_mi_number(item, MI_SSTR("expires"), p->expires) < 0 ||
193+
add_mi_number(item, MI_SSTR("desired_expires"), p->desired_expires) < 0 ||
194+
add_mi_number(item, MI_SSTR("flag"), p->flag) < 0 ||
195+
add_mi_number(item, MI_SSTR("db_flag"), p->db_flag) < 0 ||
196+
add_mi_number(item, MI_SSTR("ua_flag"), p->ua_flag) < 0)
197+
return -1;
198+
199+
if (p->sh_tag.len && add_mi_string(item, MI_SSTR("sharing_tag"),
200+
p->sh_tag.s, p->sh_tag.len) < 0)
201+
return -1;
202+
return 0;
203+
}
204+
205+
static int mi_print_presentity(mi_item_t *array, ua_pres_t *p)
206+
{
207+
mi_item_t *item, *pending, *publ_item;
208+
publ_t *publ;
209+
210+
item = add_mi_object(array, NULL, 0);
211+
if (!item || mi_print_common(item, p) < 0)
212+
return -1;
213+
214+
if (add_mi_string(item, MI_SSTR("tuple_id"),
215+
p->tuple_id.s, p->tuple_id.len) < 0 ||
216+
add_mi_number(item, MI_SSTR("waiting_reply"), p->waiting_reply) < 0)
217+
return -1;
218+
219+
if (p->etag.s && p->etag.len &&
220+
add_mi_string(item, MI_SSTR("etag"), p->etag.s, p->etag.len) < 0)
221+
return -1;
222+
223+
pending = add_mi_array(item, MI_SSTR("pending_publ"));
224+
if (!pending)
225+
return -1;
226+
for (publ = p->pending_publ; publ; publ = publ->next) {
227+
publ_item = add_mi_object(pending, NULL, 0);
228+
if (!publ_item ||
229+
add_mi_string(publ_item, MI_SSTR("content_type"),
230+
publ->content_type.s, publ->content_type.len) < 0 ||
231+
add_mi_string(publ_item, MI_SSTR("body"),
232+
publ->body.s, publ->body.len) < 0 ||
233+
add_mi_string(publ_item, MI_SSTR("extra_headers"),
234+
publ->extra_headers.s, publ->extra_headers.len) < 0 ||
235+
add_mi_number(publ_item, MI_SSTR("expires"), publ->expires) < 0)
236+
return -1;
237+
}
238+
return 0;
239+
}
240+
241+
static int mi_print_subscription(mi_item_t *array, ua_pres_t *p)
242+
{
243+
mi_item_t *item;
244+
245+
item = add_mi_object(array, NULL, 0);
246+
if (!item || mi_print_common(item, p) < 0)
247+
return -1;
248+
249+
if (add_mi_string(item, MI_SSTR("to_uri"), p->to_uri.s, p->to_uri.len) < 0 ||
250+
add_mi_string(item, MI_SSTR("watcher_uri"),
251+
p->watcher_uri->s, p->watcher_uri->len) < 0 ||
252+
add_mi_string(item, MI_SSTR("call_id"), p->call_id.s, p->call_id.len) < 0 ||
253+
add_mi_string(item, MI_SSTR("to_tag"), p->to_tag.s, p->to_tag.len) < 0 ||
254+
add_mi_string(item, MI_SSTR("from_tag"), p->from_tag.s, p->from_tag.len) < 0 ||
255+
add_mi_number(item, MI_SSTR("cseq"), p->cseq) < 0 ||
256+
add_mi_number(item, MI_SSTR("version"), p->version) < 0 ||
257+
add_mi_number(item, MI_SSTR("watcher_count"), p->watcher_count) < 0 ||
258+
add_mi_string(item, MI_SSTR("extra_headers"),
259+
p->extra_headers.s, p->extra_headers.len) < 0 ||
260+
add_mi_string(item, MI_SSTR("record_route"),
261+
p->record_route.s, p->record_route.len) < 0 ||
262+
add_mi_string(item, MI_SSTR("remote_contact"),
263+
p->remote_contact.s, p->remote_contact.len) < 0 ||
264+
add_mi_string(item, MI_SSTR("contact"), p->contact.s, p->contact.len) < 0)
265+
return -1;
266+
267+
if (p->outbound_proxy && p->outbound_proxy->len &&
268+
add_mi_string(item, MI_SSTR("outbound_proxy"),
269+
p->outbound_proxy->s, p->outbound_proxy->len) < 0)
270+
return -1;
271+
return 0;
272+
}
273+
274+
static mi_response_t *mi_list_records(const mi_params_t *params,
275+
int subscriptions)
276+
{
277+
mi_response_t *resp;
278+
mi_item_t *array;
279+
str pres_uri = STR_NULL, event_name = STR_NULL;
280+
pua_event_t *event = NULL;
281+
ua_pres_t *p;
282+
int i, rc, have_pres_uri;
283+
284+
rc = try_get_mi_string_param(params, "pres_uri", &pres_uri.s, &pres_uri.len);
285+
if (rc < -1)
286+
return init_mi_param_error();
287+
have_pres_uri = (rc == 0);
288+
rc = try_get_mi_string_param(params, "event", &event_name.s, &event_name.len);
289+
if (rc < -1)
290+
return init_mi_param_error();
291+
if (rc == 0) {
292+
event = contains_pua_event(&event_name);
293+
if (!event)
294+
return init_mi_error(400, MI_SSTR("Unknown event"));
295+
}
296+
297+
resp = init_mi_result_array(&array);
298+
if (!resp)
299+
return NULL;
300+
for (i = 0; i < HASH_SIZE; i++) {
301+
lock_get(&HashT->p_records[i].lock);
302+
for (p = HashT->p_records[i].entity->next; p; p = p->next) {
303+
/* A watcher URI identifies a subscription record. */
304+
if (!!p->watcher_uri != subscriptions)
305+
continue;
306+
if (have_pres_uri && (p->pres_uri->len != pres_uri.len ||
307+
memcmp(p->pres_uri->s, pres_uri.s, pres_uri.len) != 0))
308+
continue;
309+
if (event && p->event != event->ev_flag)
310+
continue;
311+
if ((subscriptions ? mi_print_subscription(array, p) :
312+
mi_print_presentity(array, p)) < 0) {
313+
lock_release(&HashT->p_records[i].lock);
314+
free_mi_response(resp);
315+
LM_ERR("Unable to create PUA records reply\n");
316+
return NULL;
317+
}
318+
}
319+
lock_release(&HashT->p_records[i].lock);
320+
}
321+
return resp;
322+
}
323+
324+
static mi_response_t *mi_list_presentities(const mi_params_t *params,
325+
struct mi_handler *async_hdl)
326+
{
327+
return mi_list_records(params, 0);
328+
}
329+
330+
static mi_response_t *mi_list_subscription(const mi_params_t *params,
331+
struct mi_handler *async_hdl)
332+
{
333+
return mi_list_records(params, 1);
334+
}
335+
159336
/**
160337
* init module function
161338
*/

0 commit comments

Comments
 (0)