summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/baresip.h12
-rw-r--r--modules/presence/subscriber.c42
-rw-r--r--src/contact.c42
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)
{