diff options
author | Alfred E. Heggestad <aeh@db.org> | 2016-06-06 10:14:12 +0200 |
---|---|---|
committer | Alfred E. Heggestad <aeh@db.org> | 2016-06-06 10:14:12 +0200 |
commit | 6910d50e9b1e80fe758b259149012e7e062eecd0 (patch) | |
tree | aecd149deed8ae71349e3b2e626e53f57a9c974a /src/net.c | |
parent | 362914f55831f4ad3afd7c0cad8f01f2f8b4892c (diff) |
net: make networking code re-entrant
- The network instance is now in struct network and does not
use any local/static data
- A new top-level struct in baresip.c owns the single instance
of struct network
it is a long-term goal to remove all local/static data
from libbaresip and make it fully re-entrant.
Diffstat (limited to 'src/net.c')
-rw-r--r-- | src/net.c | 324 |
1 files changed, 200 insertions, 124 deletions
@@ -1,7 +1,7 @@ /** - * @file net.c Networking code + * @file src/net.c Networking code * - * Copyright (C) 2010 Creytiv.com + * Copyright (C) 2010 - 2016 Creytiv.com */ #include <re.h> #include <baresip.h> @@ -11,7 +11,7 @@ #define MAX_NS 8 -static struct { +struct network { struct config_net cfg; struct sa laddr; char ifname[16]; @@ -28,31 +28,46 @@ static struct { char domain[64]; /**< DNS domain from network */ net_change_h *ch; void *arg; -} net; +}; -static int net_dns_srv_get(struct sa *srvv, uint32_t *n, bool *from_sys) +static int net_dnssrv_add(struct network *net, const struct sa *sa) +{ + if (!net) + return EINVAL; + + if (net->nsn >= ARRAY_SIZE(net->nsv)) + return E2BIG; + + sa_cpy(&net->nsv[net->nsn++], sa); + + return 0; +} + + +static int net_dns_srv_get(const struct network *net, + struct sa *srvv, uint32_t *n, bool *from_sys) { struct sa nsv[MAX_NS]; uint32_t i, nsn = ARRAY_SIZE(nsv); int err; - err = dns_srv_get(net.domain, sizeof(net.domain), nsv, &nsn); + err = dns_srv_get(NULL, 0, nsv, &nsn); if (err) { nsn = 0; } - if (net.nsn) { + if (net->nsn) { - if (net.nsn > *n) + if (net->nsn > *n) return E2BIG; /* Use any configured nameservers */ - for (i=0; i<net.nsn; i++) { - srvv[i] = net.nsv[i]; + for (i=0; i<net->nsn; i++) { + srvv[i] = net->nsv[i]; } - *n = net.nsn; + *n = net->nsn; if (from_sys) *from_sys = false; @@ -77,7 +92,7 @@ static int net_dns_srv_get(struct sa *srvv, uint32_t *n, bool *from_sys) /** * Check for DNS Server updates */ -static void dns_refresh(void) +static void dns_refresh(struct network *net) { struct sa nsv[MAX_NS]; uint32_t nsn; @@ -85,11 +100,11 @@ static void dns_refresh(void) nsn = ARRAY_SIZE(nsv); - err = net_dns_srv_get(nsv, &nsn, NULL); + err = net_dns_srv_get(net, nsv, &nsn, NULL); if (err) return; - (void)dnsc_srv_set(net.dnsc, nsv, nsn); + (void)dnsc_srv_set(net->dnsc, nsv, nsn); } @@ -98,16 +113,16 @@ static void dns_refresh(void) */ static void ipchange_handler(void *arg) { + struct network *net = arg; bool change; - (void)arg; - tmr_start(&net.tmr, net.interval * 1000, ipchange_handler, NULL); + tmr_start(&net->tmr, net->interval * 1000, ipchange_handler, net); - dns_refresh(); + dns_refresh(net); - change = net_check(); - if (change && net.ch) { - net.ch(net.arg); + change = net_check(net); + if (change && net->ch) { + net->ch(net->arg); } } @@ -115,49 +130,51 @@ static void ipchange_handler(void *arg) /** * Check if local IP address(es) changed * + * @param net Network instance + * * @return True if changed, otherwise false */ -bool net_check(void) +bool net_check(struct network *net) { - struct sa laddr = net.laddr; + struct sa laddr = net->laddr; #ifdef HAVE_INET6 - struct sa laddr6 = net.laddr6; + struct sa laddr6 = net->laddr6; #endif bool change = false; - if (str_isset(net.cfg.ifname)) { + if (str_isset(net->cfg.ifname)) { - (void)net_if_getaddr(net.cfg.ifname, AF_INET, &net.laddr); + (void)net_if_getaddr(net->cfg.ifname, AF_INET, &net->laddr); #ifdef HAVE_INET6 - (void)net_if_getaddr(net.cfg.ifname, AF_INET6, &net.laddr6); + (void)net_if_getaddr(net->cfg.ifname, AF_INET6, &net->laddr6); #endif } else { - (void)net_default_source_addr_get(AF_INET, &net.laddr); - (void)net_rt_default_get(AF_INET, net.ifname, - sizeof(net.ifname)); + (void)net_default_source_addr_get(AF_INET, &net->laddr); + (void)net_rt_default_get(AF_INET, net->ifname, + sizeof(net->ifname)); #ifdef HAVE_INET6 - (void)net_default_source_addr_get(AF_INET6, &net.laddr6); - (void)net_rt_default_get(AF_INET6, net.ifname6, - sizeof(net.ifname6)); + (void)net_default_source_addr_get(AF_INET6, &net->laddr6); + (void)net_rt_default_get(AF_INET6, net->ifname6, + sizeof(net->ifname6)); #endif } - if (sa_isset(&net.laddr, SA_ADDR) && - !sa_cmp(&laddr, &net.laddr, SA_ADDR)) { + if (sa_isset(&net->laddr, SA_ADDR) && + !sa_cmp(&laddr, &net->laddr, SA_ADDR)) { change = true; info("net: local IPv4 address changed: %j -> %j\n", - &laddr, &net.laddr); + &laddr, &net->laddr); } #ifdef HAVE_INET6 - if (sa_isset(&net.laddr6, SA_ADDR) && - !sa_cmp(&laddr6, &net.laddr6, SA_ADDR)) { + if (sa_isset(&net->laddr6, SA_ADDR) && + !sa_cmp(&laddr6, &net->laddr6, SA_ADDR)) { change = true; info("net: local IPv6 address changed: %j -> %j\n", - &laddr6, &net.laddr6); + &laddr6, &net->laddr6); } #endif @@ -165,17 +182,17 @@ bool net_check(void) } -static int dns_init(void) +static int dns_init(struct network *net) { struct sa nsv[MAX_NS]; uint32_t nsn = ARRAY_SIZE(nsv); int err; - err = net_dns_srv_get(nsv, &nsn, NULL); + err = net_dns_srv_get(net, nsv, &nsn, NULL); if (err) return err; - return dnsc_alloc(&net.dnsc, NULL, nsv, nsn); + return dnsc_alloc(&net->dnsc, NULL, nsv, nsn); } @@ -190,20 +207,33 @@ static bool check_ipv6(void) } +static void net_destructor(void *data) +{ + struct network *net = data; + + tmr_cancel(&net->tmr); + mem_deref(net->dnsc); +} + + /** * Initialise networking * - * @param cfg Network configuration - * @param af Preferred address family + * @param netp Pointer to allocated network instance + * @param cfg Network configuration + * @param af Preferred address family * * @return 0 if success, otherwise errorcode */ -int net_init(const struct config_net *cfg, int af) +int net_alloc(struct network **netp, const struct config_net *cfg, int af) { + struct network *net; + struct sa nsv[MAX_NS]; + uint32_t nsn = ARRAY_SIZE(nsv); char buf4[128] = "", buf6[128] = ""; int err; - if (!cfg) + if (!netp || !cfg) return EINVAL; /* @@ -225,20 +255,38 @@ int net_init(const struct config_net *cfg, int af) } #endif - net.cfg = *cfg; - net.af = af; + net = mem_zalloc(sizeof(*net), net_destructor); + if (!net) + return ENOMEM; + + net->cfg = *cfg; + net->af = af; + + tmr_init(&net->tmr); - tmr_init(&net.tmr); + if (cfg->nsc) { + size_t i; + + for (i=0; i<cfg->nsc; i++) { + + err = net_dnssrv_add(net, &cfg->nsv[i]); + if (err) { + warning("net: failed to add nameserver: %m\n", + err); + goto out; + } + } + } /* Initialise DNS resolver */ - err = dns_init(); + err = dns_init(net); if (err) { warning("net: dns_init: %m\n", err); - return err; + goto out; } - sa_init(&net.laddr, AF_INET); - (void)sa_set_str(&net.laddr, "127.0.0.1", 0); + sa_init(&net->laddr, AF_INET); + (void)sa_set_str(&net->laddr, "127.0.0.1", 0); if (str_isset(cfg->ifname)) { @@ -246,10 +294,10 @@ int net_init(const struct config_net *cfg, int af) info("Binding to interface '%s'\n", cfg->ifname); - str_ncpy(net.ifname, cfg->ifname, sizeof(net.ifname)); + str_ncpy(net->ifname, cfg->ifname, sizeof(net->ifname)); err = net_if_getaddr(cfg->ifname, - AF_INET, &net.laddr); + AF_INET, &net->laddr); if (err) { info("net: %s: could not get IPv4 address (%m)\n", cfg->ifname, err); @@ -258,11 +306,11 @@ int net_init(const struct config_net *cfg, int af) got_it = true; #ifdef HAVE_INET6 - str_ncpy(net.ifname6, cfg->ifname, - sizeof(net.ifname6)); + str_ncpy(net->ifname6, cfg->ifname, + sizeof(net->ifname6)); err = net_if_getaddr(cfg->ifname, - AF_INET6, &net.laddr6); + AF_INET6, &net->laddr6); if (err) { info("net: %s: could not get IPv6 address (%m)\n", cfg->ifname, err); @@ -275,77 +323,72 @@ int net_init(const struct config_net *cfg, int af) else { warning("net: %s: could not get network address\n", cfg->ifname); - return EADDRNOTAVAIL; + err = EADDRNOTAVAIL; + goto out; } } else { - (void)net_default_source_addr_get(AF_INET, &net.laddr); - (void)net_rt_default_get(AF_INET, net.ifname, - sizeof(net.ifname)); + (void)net_default_source_addr_get(AF_INET, &net->laddr); + (void)net_rt_default_get(AF_INET, net->ifname, + sizeof(net->ifname)); #ifdef HAVE_INET6 - sa_init(&net.laddr6, AF_INET6); + sa_init(&net->laddr6, AF_INET6); - (void)net_default_source_addr_get(AF_INET6, &net.laddr6); - (void)net_rt_default_get(AF_INET6, net.ifname6, - sizeof(net.ifname6)); + (void)net_default_source_addr_get(AF_INET6, &net->laddr6); + (void)net_rt_default_get(AF_INET6, net->ifname6, + sizeof(net->ifname6)); #endif } - if (sa_isset(&net.laddr, SA_ADDR)) { + if (sa_isset(&net->laddr, SA_ADDR)) { re_snprintf(buf4, sizeof(buf4), " IPv4=%s:%j", - net.ifname, &net.laddr); + net->ifname, &net->laddr); } #ifdef HAVE_INET6 - if (sa_isset(&net.laddr6, SA_ADDR)) { + if (sa_isset(&net->laddr6, SA_ADDR)) { re_snprintf(buf6, sizeof(buf6), " IPv6=%s:%j", - net.ifname6, &net.laddr6); + net->ifname6, &net->laddr6); } #endif + + (void)dns_srv_get(net->domain, sizeof(net->domain), nsv, &nsn); + info("Local network address: %s %s\n", buf4, buf6); + out: + if (err) + mem_deref(net); + else + *netp = net; + return err; } /** - * Reset the DNS resolver + * Use a specific DNS server + * + * @param net Network instance + * @param ns DNS Server IP address and port * * @return 0 if success, otherwise errorcode */ -int net_reset(void) -{ - net.dnsc = mem_deref(net.dnsc); - - return dns_init(); -} - - -/** - * Close networking - */ -void net_close(void) +int net_use_nameserver(struct network *net, const struct sa *ns) { - net.dnsc = mem_deref(net.dnsc); - tmr_cancel(&net.tmr); - net.nsn = 0; -} + struct dnsc *dnsc; + int err; + if (!net || !ns) + return EINVAL; -/** - * Add a DNS server - * - * @param sa DNS Server IP address and port - * - * @return 0 if success, otherwise errorcode - */ -int net_dnssrv_add(const struct sa *sa) -{ - if (net.nsn >= ARRAY_SIZE(net.nsv)) - return E2BIG; + err = dnsc_alloc(&dnsc, NULL, ns, 1); + if (err) + return err; - sa_cpy(&net.nsv[net.nsn++], sa); + mem_deref(net->dnsc); + net->dnsc = dnsc; return 0; } @@ -354,33 +397,47 @@ int net_dnssrv_add(const struct sa *sa) /** * Check for networking changes with a regular interval * + * @param net Network instance * @param interval Interval in seconds * @param ch Handler called when a change was detected * @param arg Handler argument */ -void net_change(uint32_t interval, net_change_h *ch, void *arg) +void net_change(struct network *net, uint32_t interval, + net_change_h *ch, void *arg) { - net.interval = interval; - net.ch = ch; - net.arg = arg; + if (!net) + return; + + net->interval = interval; + net->ch = ch; + net->arg = arg; if (interval) - tmr_start(&net.tmr, interval * 1000, ipchange_handler, NULL); + tmr_start(&net->tmr, interval * 1000, ipchange_handler, net); else - tmr_cancel(&net.tmr); + tmr_cancel(&net->tmr); +} + + +void net_force_change(struct network *net) +{ + if (net && net->ch) { + net->ch(net->arg); + } } -static int dns_debug(struct re_printf *pf, void *unused) +static int dns_debug(struct re_printf *pf, const struct network *net) { struct sa nsv[MAX_NS]; uint32_t i, nsn = ARRAY_SIZE(nsv); bool from_sys = false; int err; - (void)unused; + if (!net) + return 0; - err = net_dns_srv_get(nsv, &nsn, &from_sys); + err = net_dns_srv_get(net, nsv, &nsn, &from_sys); if (err) nsn = 0; @@ -393,9 +450,12 @@ static int dns_debug(struct re_printf *pf, void *unused) } -int net_af(void) +int net_af(const struct network *net) { - return net.af; + if (!net) + return AF_UNSPEC; + + return net->af; } @@ -403,30 +463,32 @@ int net_af(void) * Print networking debug information * * @param pf Print handler for debug output - * @param unused Unused parameter + * @param net Network instance * * @return 0 if success, otherwise errorcode */ -int net_debug(struct re_printf *pf, void *unused) +int net_debug(struct re_printf *pf, const struct network *net) { int err; - (void)unused; + if (!net) + return 0; err = re_hprintf(pf, "--- Network debug ---\n"); - err |= re_hprintf(pf, " Preferred AF: %s\n", net_af2name(net.af)); + err |= re_hprintf(pf, " Preferred AF: %s\n", net_af2name(net->af)); err |= re_hprintf(pf, " Local IPv4: %9s - %j\n", - net.ifname, &net.laddr); + net->ifname, &net->laddr); #ifdef HAVE_INET6 err |= re_hprintf(pf, " Local IPv6: %9s - %j\n", - net.ifname6, &net.laddr6); + net->ifname6, &net->laddr6); #endif + err |= re_hprintf(pf, " Domain: %s\n", net->domain); err |= net_if_debug(pf, NULL); err |= net_rt_debug(pf, NULL); - err |= dns_debug(pf, NULL); + err |= dns_debug(pf, net); return err; } @@ -435,17 +497,21 @@ int net_debug(struct re_printf *pf, void *unused) /** * Get the local IP Address for a specific Address Family (AF) * - * @param af Address Family + * @param net Network instance + * @param af Address Family * * @return Local IP Address */ -const struct sa *net_laddr_af(int af) +const struct sa *net_laddr_af(const struct network *net, int af) { + if (!net) + return NULL; + switch (af) { - case AF_INET: return &net.laddr; + case AF_INET: return &net->laddr; #ifdef HAVE_INET6 - case AF_INET6: return &net.laddr6; + case AF_INET6: return &net->laddr6; #endif default: return NULL; } @@ -455,20 +521,30 @@ const struct sa *net_laddr_af(int af) /** * Get the DNS Client * + * @param net Network instance + * * @return DNS Client */ -struct dnsc *net_dnsc(void) +struct dnsc *net_dnsc(const struct network *net) { - return net.dnsc; + if (!net) + return NULL; + + return net->dnsc; } /** * Get the network domain name * + * @param net Network instance + * * @return Network domain */ -const char *net_domain(void) +const char *net_domain(const struct network *net) { - return net.domain[0] ? net.domain : NULL; + if (!net) + return NULL; + + return net->domain[0] ? net->domain : NULL; } |