From 713f55a1f9958222f85238bde40482b566cf040e Mon Sep 17 00:00:00 2001 From: "Alfred E. Heggestad" Date: Sun, 24 Jul 2016 18:00:40 +0200 Subject: contact: make contacts re-entrant --- include/baresip.h | 22 ++++++++---- modules/contact/contact.c | 19 +++++++--- modules/gtk/gtk_mod.c | 3 +- modules/gtk/uri_entry.c | 3 +- modules/presence/subscriber.c | 3 +- src/baresip.c | 13 +++++++ src/contact.c | 81 ++++++++++++++++++++++++++++--------------- src/ua.c | 8 ++--- test/contact.c | 55 +++++++++++++++++++++++++++++ test/main.c | 1 + test/srcs.mk | 1 + test/test.h | 1 + 12 files changed, 162 insertions(+), 48 deletions(-) create mode 100644 test/contact.c diff --git a/include/baresip.h b/include/baresip.h index 26ddf4b..c6d8ae8 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -262,17 +262,24 @@ enum presence_status { PRESENCE_BUSY }; +struct contacts { + struct list cl; + struct hash *cht; +}; + struct contact; -int contact_init(void); -void contact_close(void); -int contact_add(struct contact **contactp, const struct pl *addr); -int contacts_print(struct re_printf *pf, void *unused); +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); +int contacts_print(struct re_printf *pf, const struct contacts *contacts); void contact_set_presence(struct contact *c, enum presence_status status); -bool contact_block_access(const char *uri); -struct contact *contact_find(const char *uri); +bool contact_block_access(const struct contacts *contacts, const char *uri); +struct contact *contact_find(const struct contacts *contacts, + const char *uri); struct sip_addr *contact_addr(const struct contact *c); -struct list *contact_list(void); +struct list *contact_list(const struct contacts *contacts); const char *contact_str(const struct contact *c); const char *contact_presence_str(enum presence_status status); @@ -1076,6 +1083,7 @@ double mos_calculate(double *r_factor, double rtt, int baresip_init(struct config *cfg, bool prefer_ipv6); void baresip_close(void); struct network *baresip_network(void); +struct contacts *baresip_contacts(void); #ifdef __cplusplus diff --git a/modules/contact/contact.c b/modules/contact/contact.c index 42ff614..2a566eb 100644 --- a/modules/contact/contact.c +++ b/modules/contact/contact.c @@ -24,13 +24,14 @@ static char cmd_desc[128] = "Send MESSAGE to peer"; static int confline_handler(const struct pl *addr) { - return contact_add(NULL, addr); + return contact_add(baresip_contacts(), NULL, addr); } static int cmd_contact(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; + struct contacts *contacts = baresip_contacts(); struct contact *cnt = NULL; struct pl dname, user, pl; struct le *le; @@ -42,7 +43,7 @@ static int cmd_contact(struct re_printf *pf, void *arg) err |= re_hprintf(pf, "\n"); - for (le = list_head(contact_list()); le; le = le->next) { + for (le = list_head(contact_list(contacts)); le; le = le->next) { struct contact *c = le->data; @@ -101,6 +102,13 @@ static int cmd_contact(struct re_printf *pf, void *arg) } +static int print_contacts(struct re_printf *pf, void *unused) +{ + (void)unused; + return contacts_print(pf, baresip_contacts()); +} + + static int cmd_message(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; @@ -120,7 +128,7 @@ static int cmd_message(struct re_printf *pf, void *arg) static const struct cmd cmdv[] = { {'/', CMD_IPRM, "Dial from contacts", cmd_contact }, {'=', CMD_IPRM, "Select chat peer", cmd_contact }, - {'C', 0, "List contacts", contacts_print }, + {'C', 0, "List contacts", print_contacts }, {'-', CMD_PRM, cmd_desc, cmd_message }, }; @@ -201,7 +209,8 @@ static int module_init(void) if (err) return err; - info("Populated %u contacts\n", list_count(contact_list())); + info("Populated %u contacts\n", + list_count(contact_list(baresip_contacts()))); return err; } @@ -210,7 +219,7 @@ static int module_init(void) static int module_close(void) { cmd_unregister(cmdv); - list_flush(contact_list()); + list_flush(contact_list(baresip_contacts())); return 0; } diff --git a/modules/gtk/gtk_mod.c b/modules/gtk/gtk_mod.c index 5e01882..55559d8 100644 --- a/modules/gtk/gtk_mod.c +++ b/modules/gtk/gtk_mod.c @@ -142,12 +142,13 @@ static void menu_on_dial_contact(GtkMenuItem *menuItem, gpointer arg) static void init_contacts_menu(struct gtk_mod *mod) { + struct contacts *contacts = baresip_contacts(); struct le *le; GtkWidget *item; GtkMenuShell *contacts_menu = GTK_MENU_SHELL(mod->contacts_menu); /* Add contacts to submenu */ - for (le = list_head(contact_list()); le; le = le->next) { + for (le = list_head(contact_list(contacts)); le; le = le->next) { struct contact *c = le->data; item = gtk_menu_item_new_with_label(contact_str(c)); gtk_menu_shell_append(contacts_menu, item); diff --git a/modules/gtk/uri_entry.c b/modules/gtk/uri_entry.c index 601bf83..0ca1a3d 100644 --- a/modules/gtk/uri_entry.c +++ b/modules/gtk/uri_entry.c @@ -18,6 +18,7 @@ */ GtkWidget *uri_combo_box_new(void) { + struct contacts *contacts = baresip_contacts(); struct le *le; GtkEntry *uri_entry; GtkWidget *uri_combobox; @@ -26,7 +27,7 @@ GtkWidget *uri_combo_box_new(void) uri_entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(uri_combobox))); gtk_entry_set_activates_default(uri_entry, TRUE); - for (le = list_head(contact_list()); le; le = le->next) { + for (le = list_head(contact_list(contacts)); le; le = le->next) { struct contact *c = le->data; gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT(uri_combobox), diff --git a/modules/presence/subscriber.c b/modules/presence/subscriber.c index baf0b0c..b61e454 100644 --- a/modules/presence/subscriber.c +++ b/modules/presence/subscriber.c @@ -282,10 +282,11 @@ static int presence_alloc(struct contact *contact) int subscriber_init(void) { + struct contacts *contacts = baresip_contacts(); struct le *le; int err = 0; - for (le = list_head(contact_list()); le; le = le->next) { + for (le = list_head(contact_list(contacts)); le; le = le->next) { struct contact *c = le->data; struct sip_addr *addr = contact_addr(c); diff --git a/src/baresip.c b/src/baresip.c index f70824c..72d13f1 100644 --- a/src/baresip.c +++ b/src/baresip.c @@ -14,6 +14,7 @@ */ static struct baresip { struct network *net; + struct contacts contacts; } baresip; @@ -35,12 +36,18 @@ int baresip_init(struct config *cfg, bool prefer_ipv6) return err; } + err = contact_init(&baresip.contacts); + if (err) + return err; + return 0; } void baresip_close(void) { + contact_close(&baresip.contacts); + baresip.net = mem_deref(baresip.net); } @@ -49,3 +56,9 @@ struct network *baresip_network(void) { return baresip.net; } + + +struct contacts *baresip_contacts(void) +{ + return &baresip.contacts; +} diff --git a/src/contact.c b/src/contact.c index e8e6df6..1fe308b 100644 --- a/src/contact.c +++ b/src/contact.c @@ -3,6 +3,7 @@ * * Copyright (C) 2010 Creytiv.com */ +#include #include #include @@ -22,9 +23,6 @@ struct contact { enum access access; }; -static struct list cl; -static struct hash *cht; - static void destructor(void *arg) { @@ -39,18 +37,20 @@ static void destructor(void *arg) /** * Add a contact * + * @param contacts Contacts container * @param contactp Pointer to allocated contact (optional) * @param addr Contact in SIP address format * * @return 0 if success, otherwise errorcode */ -int contact_add(struct contact **contactp, const struct pl *addr) +int contact_add(struct contacts *contacts, + struct contact **contactp, const struct pl *addr) { struct contact *c; struct pl pl; int err; - if (!cht) + if (!contacts) return EINVAL; c = mem_zalloc(sizeof(*c), destructor); @@ -89,8 +89,8 @@ int contact_add(struct contact **contactp, const struct pl *addr) c->status = PRESENCE_UNKNOWN; - list_append(&cl, &c->le, c); - hash_append(cht, hash_joaat_pl(&c->addr.auri), &c->he, c); + list_append(&contacts->cl, &c->le, c); + hash_append(contacts->cht, hash_joaat_pl(&c->addr.auri), &c->he, c); out: if (err) @@ -131,11 +131,16 @@ const char *contact_str(const struct contact *c) /** * Get the list of contacts * + * @param contacts Contacts container + * * @return List of contacts */ -struct list *contact_list(void) +struct list *contact_list(const struct contacts *contacts) { - return &cl; + if (!contacts) + return NULL; + + return (struct list *)&contacts->cl; } @@ -168,17 +173,21 @@ const char *contact_presence_str(enum presence_status status) } -int contacts_print(struct re_printf *pf, void *unused) +int contacts_print(struct re_printf *pf, const struct contacts *contacts) { + const struct list *lst; struct le *le; int err; - (void)unused; + if (!contacts) + return 0; + + lst = contact_list(contacts); err = re_hprintf(pf, "\n--- Contacts: (%u) ---\n", - list_count(contact_list())); + list_count(lst)); - for (le = list_head(contact_list()); le && !err; le = le->next) { + for (le = list_head(lst); le && !err; le = le->next) { const struct contact *c = le->data; const struct sip_addr *addr = &c->addr; @@ -196,27 +205,40 @@ int contacts_print(struct re_printf *pf, void *unused) /** * Initialise the contacts sub-system * + * @param contacts Contacts container + * * @return 0 if success, otherwise errorcode */ -int contact_init(void) +int contact_init(struct contacts *contacts) { int err = 0; - if (!cht) - err = hash_alloc(&cht, 32); + if (!contacts) + return EINVAL; + + memset(contacts, 0, sizeof(*contacts)); + + list_init(&contacts->cl); + + err = hash_alloc(&contacts->cht, 32); return err; } /** + * @param contacts Contacts container + * * Close the contacts sub-system */ -void contact_close(void) +void contact_close(struct contacts *contacts) { - hash_clear(cht); - cht = mem_deref(cht); - list_flush(&cl); + if (!contacts) + return; + + hash_clear(contacts->cht); + contacts->cht = mem_deref(contacts->cht); + list_flush(&contacts->cl); } @@ -231,13 +253,17 @@ static bool find_handler(struct le *le, void *arg) /** * Lookup a SIP uri in all registered contacts * - * @param uri SIP uri to lookup + * @param contacts Contacts container + * @param uri SIP uri to lookup * * @return Matching contact if found, otherwise NULL */ -struct contact *contact_find(const char *uri) +struct contact *contact_find(const struct contacts *contacts, const char *uri) { - return list_ledata(hash_lookup(cht, hash_joaat_str(uri), + if (!contacts) + return NULL; + + return list_ledata(hash_lookup(contacts->cht, hash_joaat_str(uri), find_handler, (void *)uri)); } @@ -248,19 +274,20 @@ struct contact *contact_find(const char *uri) * - Matching uri has first presedence * - Global uri has second presedence * - * @param uri SIP uri to check for access + * @param contacts Contacts container + * @param uri SIP uri to check for access * * @return True if blocked, false if allowed */ -bool contact_block_access(const char *uri) +bool contact_block_access(const struct contacts *contacts, const char *uri) { struct contact *c; - c = contact_find(uri); + c = contact_find(contacts, uri); if (c && c->access != ACCESS_UNKNOWN) return c->access == ACCESS_BLOCK; - c = contact_find("sip:*@*"); + c = contact_find(contacts, "sip:*@*"); if (c && c->access != ACCESS_UNKNOWN) return c->access == ACCESS_BLOCK; diff --git a/src/ua.c b/src/ua.c index 3d0e935..35626f7 100644 --- a/src/ua.c +++ b/src/ua.c @@ -302,7 +302,8 @@ static void call_event_handler(struct call *call, enum call_event ev, case CALL_EVENT_INCOMING: - if (contact_block_access(peeruri)) { + if (contact_block_access(baresip_contacts(), + peeruri)) { info("ua: blocked access: \"%s\"\n", peeruri); @@ -1336,10 +1337,6 @@ int ua_init(const char *software, bool udp, bool tcp, bool tls, play_init(); - err = contact_init(); - if (err) - return err; - uag.use_udp = udp; uag.use_tcp = tcp; uag.use_tls = tls; @@ -1395,7 +1392,6 @@ void ua_close(void) cmd_unregister(cmdv); play_close(); ui_reset(); - contact_close(); uag.evsock = mem_deref(uag.evsock); uag.sock = mem_deref(uag.sock); diff --git a/test/contact.c b/test/contact.c new file mode 100644 index 0000000..5b357ff --- /dev/null +++ b/test/contact.c @@ -0,0 +1,55 @@ +/** + * @file test/contact.c Baresip selftest -- contacts + * + * Copyright (C) 2010 - 2016 Creytiv.com + */ +#include +#include +#include +#include "test.h" + + +int test_contact(void) +{ + struct contacts contacts; + struct contact *c; + const char *addr = "sip:neil@young.com"; + struct pl pl_addr; + int err; + + err = contact_init(&contacts); + ASSERT_EQ(0, err); + + /* Verify that we have no contacts */ + + ASSERT_EQ(0, list_count(contact_list(&contacts))); + + c = contact_find(&contacts, "sip:null@void.com"); + ASSERT_TRUE(c == NULL); + + /* Add one contact, list should have one entry and + find should return the added contact */ + + pl_set_str(&pl_addr, addr); + err = contact_add(&contacts, &c, &pl_addr); + ASSERT_EQ(0, err); + ASSERT_TRUE(c != NULL); + + ASSERT_EQ(1, list_count(contact_list(&contacts))); + + c = contact_find(&contacts, addr); + ASSERT_TRUE(c != NULL); + + ASSERT_STREQ(addr, contact_str(c)); + + /* Delete 1 contact, verify that list is empty */ + + mem_deref(c); + + ASSERT_EQ(0, list_count(contact_list(&contacts))); + + out: + contact_close(&contacts); + + return err; +} diff --git a/test/main.c b/test/main.c index c9f1964..c0bc1c1 100644 --- a/test/main.c +++ b/test/main.c @@ -28,6 +28,7 @@ static const struct test tests[] = { TEST(test_call_multiple), TEST(test_call_max), TEST(test_cmd), + TEST(test_contact), TEST(test_cplusplus), TEST(test_mos), TEST(test_network), diff --git a/test/srcs.mk b/test/srcs.mk index 06b4482..2158ca8 100644 --- a/test/srcs.mk +++ b/test/srcs.mk @@ -9,6 +9,7 @@ # Test-cases: # TEST_SRCS += cmd.c +TEST_SRCS += contact.c TEST_SRCS += ua.c TEST_SRCS += cplusplus.c TEST_SRCS += call.c diff --git a/test/test.h b/test/test.h index e8217c9..489f8e0 100644 --- a/test/test.h +++ b/test/test.h @@ -87,6 +87,7 @@ int dns_server_add_srv(struct dns_server *srv, const char *name, /* test cases */ int test_cmd(void); +int test_contact(void); int test_ua_alloc(void); int test_uag_find_param(void); int test_ua_register(void); -- cgit v1.2.3