diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/contact.c | 107 | ||||
-rw-r--r-- | src/ua.c | 15 |
2 files changed, 122 insertions, 0 deletions
diff --git a/src/contact.c b/src/contact.c index c06c7a1..e8e6df6 100644 --- a/src/contact.c +++ b/src/contact.c @@ -7,20 +7,30 @@ #include <baresip.h> +enum access { + ACCESS_UNKNOWN = 0, + ACCESS_BLOCK, + ACCESS_ALLOW +}; + struct contact { struct le le; + struct le he; /* hash-element with key 'auri' */ struct sip_addr addr; char *buf; enum presence_status status; + enum access access; }; static struct list cl; +static struct hash *cht; static void destructor(void *arg) { struct contact *c = arg; + hash_unlink(&c->he); list_unlink(&c->le); mem_deref(c->buf); } @@ -40,6 +50,9 @@ int contact_add(struct contact **contactp, const struct pl *addr) struct pl pl; int err; + if (!cht) + return EINVAL; + c = mem_zalloc(sizeof(*c), destructor); if (!c) return ENOMEM; @@ -56,9 +69,28 @@ int contact_add(struct contact **contactp, const struct pl *addr) goto out; } + if (0 == msg_param_decode(&c->addr.params, "access", &pl)) { + + if (0 == pl_strcasecmp(&pl, "block")) { + c->access = ACCESS_BLOCK; + } + else if (0 == pl_strcasecmp(&pl, "allow")) { + c->access = ACCESS_ALLOW; + } + else { + warning("contact: unknown 'access=%r' for '%r'\n", + &pl, addr); + err = EINVAL; + goto out; + } + } + else + c->access = ACCESS_UNKNOWN; + c->status = PRESENCE_UNKNOWN; list_append(&cl, &c->le, c); + hash_append(cht, hash_joaat_pl(&c->addr.auri), &c->he, c); out: if (err) @@ -159,3 +191,78 @@ int contacts_print(struct re_printf *pf, void *unused) return err; } + + +/** + * Initialise the contacts sub-system + * + * @return 0 if success, otherwise errorcode + */ +int contact_init(void) +{ + int err = 0; + + if (!cht) + err = hash_alloc(&cht, 32); + + return err; +} + + +/** + * Close the contacts sub-system + */ +void contact_close(void) +{ + hash_clear(cht); + cht = mem_deref(cht); + list_flush(&cl); +} + + +static bool find_handler(struct le *le, void *arg) +{ + struct contact *c = le->data; + + return 0 == pl_strcmp(&c->addr.auri, arg); +} + + +/** + * Lookup a SIP uri in all registered contacts + * + * @param uri SIP uri to lookup + * + * @return Matching contact if found, otherwise NULL + */ +struct contact *contact_find(const char *uri) +{ + return list_ledata(hash_lookup(cht, hash_joaat_str(uri), + find_handler, (void *)uri)); +} + + +/** + * Check the access parameter of a SIP uri + * + * - Matching uri has first presedence + * - Global <sip:*@*> uri has second presedence + * + * @param uri SIP uri to check for access + * + * @return True if blocked, false if allowed + */ +bool contact_block_access(const char *uri) +{ + struct contact *c; + + c = contact_find(uri); + if (c && c->access != ACCESS_UNKNOWN) + return c->access == ACCESS_BLOCK; + + c = contact_find("sip:*@*"); + if (c && c->access != ACCESS_UNKNOWN) + return c->access == ACCESS_BLOCK; + + return false; +} @@ -266,6 +266,16 @@ static void call_event_handler(struct call *call, enum call_event ev, switch (ev) { case CALL_EVENT_INCOMING: + + if (contact_block_access(peeruri)) { + + info("ua: blocked access: \"%s\"\n", peeruri); + + ua_event(ua, UA_EVENT_CALL_CLOSED, call, str); + mem_deref(call); + break; + } + switch (ua->acc->answermode) { case ANSWERMODE_EARLY: @@ -1157,6 +1167,10 @@ int ua_init(const char *software, bool udp, bool tcp, bool tls, play_init(); + err = contact_init(); + if (err) + return err; + /* Initialise Network */ err = net_init(&cfg->net, prefer_ipv6 ? AF_INET6 : AF_INET); if (err) { @@ -1219,6 +1233,7 @@ void ua_close(void) net_close(); play_close(); ui_reset(); + contact_close(); uag.evsock = mem_deref(uag.evsock); uag.sock = mem_deref(uag.sock); |