diff options
-rw-r--r-- | include/baresip.h | 12 | ||||
-rw-r--r-- | modules/presence/subscriber.c | 42 | ||||
-rw-r--r-- | src/contact.c | 42 |
3 files changed, 95 insertions, 1 deletions
diff --git a/include/baresip.h b/include/baresip.h index de83fe4..d1c8524 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -283,18 +283,28 @@ enum presence_status { PRESENCE_BUSY }; + +struct contact; +typedef void (contact_update_h)(struct contact *c, bool remove, void *arg); + struct contacts { struct list cl; struct hash *cht; + + contact_update_h *handler; + void* handler_arg; }; -struct contact; int contact_init(struct contacts *contacts); void contact_close(struct contacts *contacts); int contact_add(struct contacts *contacts, struct contact **contactp, const struct pl *addr); +void contact_remove(struct contacts *contacts, struct contact *c); +void contact_set_update_handler(struct contacts *contacs, + contact_update_h *updateh, void *arg); int contacts_print(struct re_printf *pf, const struct contacts *contacts); +enum presence_status contact_presence(const struct contact *c); void contact_set_presence(struct contact *c, enum presence_status status); bool contact_block_access(const struct contacts *contacts, const char *uri); struct contact *contact_find(const struct contacts *contacts, diff --git a/modules/presence/subscriber.c b/modules/presence/subscriber.c index 596e592..914f74d 100644 --- a/modules/presence/subscriber.c +++ b/modules/presence/subscriber.c @@ -280,6 +280,43 @@ static int presence_alloc(struct contact *contact) return 0; } +static void contact_handler(struct contact *contact, + bool removed, void *arg) +{ + struct le *le; + struct pl val; + struct presence *pres = NULL; + struct sip_addr *addr = contact_addr(contact); + (void)arg; + + if (0 == msg_param_decode(&addr->params, "presence", &val) && + 0 == pl_strcasecmp(&val, "p2p")) { + if (!removed) { + if (presence_alloc(contact) != 0) { + error("presence: presence_alloc failed\n"); + return; + } + } + else { + /* Find matching presence element for contact */ + for (le = list_head(&presencel); le; le = le->next) { + pres = (struct presence*)le->data; + if (pres->contact == contact) { + break; + } + pres = NULL; + } + + if (pres) { + mem_deref(pres); + } + else { + error("presence: No contact to remove\n"); + } + } + } +} + int subscriber_init(void) { @@ -302,12 +339,15 @@ int subscriber_init(void) info("Subscribing to %u contacts\n", list_count(&presencel)); + contact_set_update_handler(contacts, contact_handler, NULL); + return err; } void subscriber_close(void) { + contact_set_update_handler(baresip_contacts(), NULL, NULL); list_flush(&presencel); } @@ -319,6 +359,8 @@ void subscriber_close_all(void) info("presence: subscriber: closing %u subs\n", list_count(&presencel)); + contact_set_update_handler(baresip_contacts(), NULL, NULL); + le = presencel.head; while (le) { diff --git a/src/contact.c b/src/contact.c index 1fe308b..7d0d621 100644 --- a/src/contact.c +++ b/src/contact.c @@ -92,6 +92,9 @@ int contact_add(struct contacts *contacts, list_append(&contacts->cl, &c->le, c); hash_append(contacts->cht, hash_joaat_pl(&c->addr.auri), &c->he, c); + if (contacts->handler) + contacts->handler(c, false, contacts->handler_arg); + out: if (err) mem_deref(c); @@ -103,6 +106,38 @@ int contact_add(struct contacts *contacts, /** + * Remove a contact + * + * @param contacts Contacts container + * @param contactp Pointer to the contact to be removed + */ +void contact_remove(struct contacts *contacts, struct contact *contact) +{ + if (!contacts || !contact) + return; + + if (contacts->handler) + contacts->handler(contact, true, contacts->handler_arg); + + hash_unlink(&contact->he); + list_unlink(&contact->le); + + mem_deref(contact); +} + +void contact_set_update_handler(struct contacts *contacts, + contact_update_h *updateh, void *arg) +{ + if (!contacts) { + return; + } + + contacts->handler = updateh; + contacts->handler_arg = arg; +} + + +/** * Get the SIP address of a contact * * @param c Contact @@ -159,6 +194,13 @@ void contact_set_presence(struct contact *c, enum presence_status status) c->status = status; } +enum presence_status contact_presence(const struct contact *c) +{ + if (!c) + return PRESENCE_UNKNOWN; + + return c->status; +} const char *contact_presence_str(enum presence_status status) { |