From 6910d50e9b1e80fe758b259149012e7e062eecd0 Mon Sep 17 00:00:00 2001 From: "Alfred E. Heggestad" Date: Mon, 6 Jun 2016 10:14:12 +0200 Subject: 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. --- docs/TODO | 2 + include/baresip.h | 34 +++-- modules/account/account.c | 2 +- modules/contact/contact.c | 2 +- modules/menu/menu.c | 8 +- modules/natbd/natbd.c | 8 +- modules/rst/rst.c | 3 +- src/baresip.c | 51 ++++++++ src/call.c | 9 +- src/config.c | 15 ++- src/core.h | 7 - src/main.c | 12 ++ src/net.c | 324 ++++++++++++++++++++++++++++------------------ src/srcs.mk | 1 + src/ua.c | 38 +++--- test/main.c | 8 ++ test/net.c | 46 +++++++ test/srcs.mk | 1 + test/test.h | 1 + test/ua.c | 6 +- 20 files changed, 400 insertions(+), 178 deletions(-) create mode 100644 src/baresip.c create mode 100644 test/net.c diff --git a/docs/TODO b/docs/TODO index 04acb40..ad7104f 100644 --- a/docs/TODO +++ b/docs/TODO @@ -20,6 +20,8 @@ Version v0.x.y: add a FPS (framerate) throttler for fast vidsrc modules + long term goal: a fully re-entrant libbaresip with no static data + ------------------------------------------------------------------------------- BUGS: diff --git a/include/baresip.h b/include/baresip.h index d60b0a5..f7f3c70 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -200,6 +200,8 @@ struct config_avt { /* Network */ struct config_net { char ifname[16]; /**< Bind to interface (optional) */ + struct sa nsv[4]; /**< DNS nameservers */ + size_t nsc; /**< Number of DNS nameservers */ }; #ifdef USE_VIDEO @@ -459,18 +461,21 @@ const struct menc *menc_find(const char *id); * Net - Networking */ +struct network; + typedef void (net_change_h)(void *arg); -int net_init(const struct config_net *cfg, int af); -void net_close(void); -int net_dnssrv_add(const struct sa *sa); -void net_change(uint32_t interval, net_change_h *ch, void *arg); -bool net_check(void); -int net_af(void); -int net_debug(struct re_printf *pf, void *unused); -const struct sa *net_laddr_af(int af); -const char *net_domain(void); -struct dnsc *net_dnsc(void); +int net_alloc(struct network **netp, const struct config_net *cfg, int af); +int net_use_nameserver(struct network *net, const struct sa *ns); +void net_change(struct network *net, uint32_t interval, + net_change_h *ch, void *arg); +void net_force_change(struct network *net); +bool net_check(struct network *net); +int net_af(const struct network *net); +int net_debug(struct re_printf *pf, const struct network *net); +const struct sa *net_laddr_af(const struct network *net, int af); +const char *net_domain(const struct network *net); +struct dnsc *net_dnsc(const struct network *net); /* @@ -1050,6 +1055,15 @@ double mos_calculate(double *r_factor, double rtt, double jitter, uint32_t num_packets_lost); +/* + * Baresip instance + */ + +int baresip_init(struct config *cfg, bool prefer_ipv6); +void baresip_close(void); +struct network *baresip_network(void); + + #ifdef __cplusplus } #endif diff --git a/modules/account/account.c b/modules/account/account.c index 46a6861..9cd4235 100644 --- a/modules/account/account.c +++ b/modules/account/account.c @@ -45,7 +45,7 @@ static int account_write_template(const char *file) pass = "pass"; } - domain = net_domain(); + domain = net_domain(baresip_network()); if (!domain) domain = "domain"; diff --git a/modules/contact/contact.c b/modules/contact/contact.c index ef10bc8..42ff614 100644 --- a/modules/contact/contact.c +++ b/modules/contact/contact.c @@ -139,7 +139,7 @@ static int write_template(const char *file) user = sys_username(); if (!user) user = "user"; - domain = net_domain(); + domain = net_domain(baresip_network()); if (!domain) domain = "domain"; diff --git a/modules/menu/menu.c b/modules/menu/menu.c index de179c1..039cf45 100644 --- a/modules/menu/menu.c +++ b/modules/menu/menu.c @@ -429,6 +429,12 @@ static int cmd_config_print(struct re_printf *pf, void *unused) } +static int cmd_net_debug(struct re_printf *pf, void *unused) +{ + return net_debug(pf, baresip_network()); +} + + static const struct cmd cmdv[] = { {'M', 0, "Main loop debug", re_debug }, {'\n', 0, "Accept incoming call", cmd_answer }, @@ -440,7 +446,7 @@ static const struct cmd cmdv[] = { {'i', 0, "SIP debug", ua_print_sip_status }, {'l', 0, "List active calls", cmd_print_calls }, {'m', 0, "Module debug", mod_debug }, - {'n', 0, "Network debug", net_debug }, + {'n', 0, "Network debug", cmd_net_debug }, {'o', CMD_PRM, "Options", options_command }, {'r', 0, "Registration info", ua_print_reg_status }, {'s', 0, "System info", print_system_info }, diff --git a/modules/natbd/natbd.c b/modules/natbd/natbd.c index 0aad61f..428a51a 100644 --- a/modules/natbd/natbd.c +++ b/modules/natbd/natbd.c @@ -244,6 +244,7 @@ static void destructor(void *arg) static int natbd_start(struct natbd *natbd) { + struct network *net = baresip_network(); int err = 0; if (!natbd->nh) { @@ -258,7 +259,8 @@ static int natbd_start(struct natbd *natbd) } if (!natbd->nm) { - err |= nat_mapping_alloc(&natbd->nm, net_laddr_af(net_af()), + err |= nat_mapping_alloc(&natbd->nm, + net_laddr_af(net, net_af(net)), &natbd->stun_srv, natbd->proto, NULL, nat_mapping_handler, natbd); err |= nat_mapping_start(natbd->nm); @@ -370,9 +372,9 @@ static void timeout_init(void *arg) goto out; } - err = stun_server_discover(&natbd->dns, net_dnsc(), + err = stun_server_discover(&natbd->dns, net_dnsc(baresip_network()), stun_usage_binding, - proto_str, net_af(), + proto_str, net_af(baresip_network()), natbd->host, natbd->port, dns_handler, natbd); if (err) diff --git a/modules/rst/rst.c b/modules/rst/rst.c index 8f2fea3..83298a9 100644 --- a/modules/rst/rst.c +++ b/modules/rst/rst.c @@ -308,7 +308,8 @@ static int rst_connect(struct rst *rst) } } else { - err = dnsc_query(&rst->dnsq, net_dnsc(), rst->host, DNS_TYPE_A, + err = dnsc_query(&rst->dnsq, net_dnsc(baresip_network()), + rst->host, DNS_TYPE_A, DNS_CLASS_IN, true, dns_handler, rst); if (err) { warning("rst: dns query error: %m\n", err); diff --git a/src/baresip.c b/src/baresip.c new file mode 100644 index 0000000..f70824c --- /dev/null +++ b/src/baresip.c @@ -0,0 +1,51 @@ +/** + * @file baresip.c Top-level baresip struct + * + * Copyright (C) 2010 - 2016 Creytiv.com + */ +#include +#include +#include "core.h" + + +/* + * Top-level struct that holds all other subsystems + * (move this instance to main.c later) + */ +static struct baresip { + struct network *net; + +} baresip; + + +int baresip_init(struct config *cfg, bool prefer_ipv6) +{ + int err; + + if (!cfg) + return EINVAL; + + baresip.net = mem_deref(baresip.net); + + /* Initialise Network */ + err = net_alloc(&baresip.net, &cfg->net, + prefer_ipv6 ? AF_INET6 : AF_INET); + if (err) { + warning("ua: network init failed: %m\n", err); + return err; + } + + return 0; +} + + +void baresip_close(void) +{ + baresip.net = mem_deref(baresip.net); +} + + +struct network *baresip_network(void) +{ + return baresip.net; +} diff --git a/src/call.c b/src/call.c index 913ea25..6d07639 100644 --- a/src/call.c +++ b/src/call.c @@ -478,7 +478,8 @@ int call_alloc(struct call **callp, const struct config *cfg, struct list *lst, goto out; /* Init SDP info */ - err = sdp_session_alloc(&call->sdp, net_laddr_af(call->af)); + err = sdp_session_alloc(&call->sdp, + net_laddr_af(baresip_network(), call->af)); if (err) goto out; @@ -493,7 +494,8 @@ int call_alloc(struct call **callp, const struct config *cfg, struct list *lst, /* Initialise media NAT handling */ if (acc->mnat) { - err = acc->mnat->sessh(&call->mnats, net_dnsc(), call->af, + err = acc->mnat->sessh(&call->mnats, + net_dnsc(baresip_network()), call->af, acc->stun_host, acc->stun_port, acc->stun_user, acc->stun_pass, call->sdp, !got_offer, @@ -1502,7 +1504,8 @@ int call_reset_transp(struct call *call) if (!call) return EINVAL; - sdp_session_set_laddr(call->sdp, net_laddr_af(call->af)); + sdp_session_set_laddr(call->sdp, + net_laddr_af(baresip_network(), call->af)); return call_modify(call); } diff --git a/src/config.c b/src/config.c index b1506f9..ed4db42 100644 --- a/src/config.c +++ b/src/config.c @@ -94,22 +94,25 @@ static int range_print(struct re_printf *pf, const struct range *rng) static int dns_server_handler(const struct pl *pl, void *arg) { + struct config_net *cfg = arg; struct sa sa; int err; - (void)arg; - err = sa_decode(&sa, pl->p, pl->l); if (err) { warning("config: dns_server: could not decode `%r'\n", pl); return err; } - err = net_dnssrv_add(&sa); - if (err) { - warning("config: failed to add nameserver %r: %m\n", pl, err); + if (cfg->nsc >= ARRAY_SIZE(cfg->nsv)) { + warning("config: too many DNS nameservers (max %zu)\n", + ARRAY_SIZE(cfg->nsv)); + return EOVERFLOW; } + /* Append dns_server to the network config */ + cfg->nsv[cfg->nsc++] = sa; + return err; } @@ -216,7 +219,7 @@ int config_parse_conf(struct config *cfg, const struct conf *conf) } /* Network */ - (void)conf_apply(conf, "dns_server", dns_server_handler, NULL); + (void)conf_apply(conf, "dns_server", dns_server_handler, &cfg->net); (void)conf_get_str(conf, "net_interface", cfg->net.ifname, sizeof(cfg->net.ifname)); diff --git a/src/core.h b/src/core.h index 88e53c1..dca28b5 100644 --- a/src/core.h +++ b/src/core.h @@ -234,13 +234,6 @@ int module_init(const struct conf *conf); void module_app_unload(void); -/* - * Network - */ - -int net_reset(void); - - /* * Register client */ diff --git a/src/main.c b/src/main.c index 29e4785..418fdc8 100644 --- a/src/main.c +++ b/src/main.c @@ -157,6 +157,16 @@ int main(int argc, char *argv[]) goto out; } + /* + * Initialise the top-level baresip struct, must be + * done AFTER configuration is complete. + */ + err = baresip_init(conf_config(), prefer_ipv6); + if (err) { + warning("main: baresip init failed (%m)\n", err); + goto out; + } + /* NOTE: must be done after all arguments are processed */ if (modc) { size_t i; @@ -219,6 +229,8 @@ int main(int argc, char *argv[]) ua_close(); conf_close(); + baresip_close(); + libre_close(); /* Check for memory leaks */ diff --git a/src/net.c b/src/net.c index 02b9cda..7c12580 100644 --- a/src/net.c +++ b/src/net.c @@ -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 #include @@ -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; insn; 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; insc; 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; } diff --git a/src/srcs.mk b/src/srcs.mk index 1ef6a4e..c538600 100644 --- a/src/srcs.mk +++ b/src/srcs.mk @@ -10,6 +10,7 @@ SRCS += audio.c SRCS += aufilt.c SRCS += auplay.c SRCS += ausrc.c +SRCS += baresip.c SRCS += call.c SRCS += cmd.c SRCS += conf.c diff --git a/src/ua.c b/src/ua.c index 6c7c758..5ca8367 100644 --- a/src/ua.c +++ b/src/ua.c @@ -1147,18 +1147,18 @@ static int add_transp_af(const struct sa *laddr) } -static int ua_add_transp(void) +static int ua_add_transp(struct network *net) { int err = 0; if (!uag.prefer_ipv6) { - if (sa_isset(net_laddr_af(AF_INET), SA_ADDR)) - err |= add_transp_af(net_laddr_af(AF_INET)); + if (sa_isset(net_laddr_af(net, AF_INET), SA_ADDR)) + err |= add_transp_af(net_laddr_af(net, AF_INET)); } #if HAVE_INET6 - if (sa_isset(net_laddr_af(AF_INET6), SA_ADDR)) - err |= add_transp_af(net_laddr_af(AF_INET6)); + if (sa_isset(net_laddr_af(net, AF_INET6), SA_ADDR)) + err |= add_transp_af(net_laddr_af(net, AF_INET6)); #endif return err; @@ -1252,7 +1252,8 @@ static void net_change_handler(void *arg) { (void)arg; - info("IP-address changed: %j\n", net_laddr_af(AF_INET)); + info("IP-address changed: %j\n", + net_laddr_af(baresip_network(), AF_INET)); (void)uag_reset_transp(true, true); } @@ -1312,9 +1313,15 @@ int ua_init(const char *software, bool udp, bool tcp, bool tls, bool prefer_ipv6) { struct config *cfg = conf_config(); + struct network *net = baresip_network(); uint32_t bsize; int err; + if (!net) { + warning("ua: no network\n"); + return EINVAL; + } + uag.cfg = &cfg->sip; bsize = cfg->sip.trans_bsize; @@ -1324,13 +1331,6 @@ int ua_init(const char *software, bool udp, bool tcp, bool tls, if (err) return err; - /* Initialise Network */ - err = net_init(&cfg->net, prefer_ipv6 ? AF_INET6 : AF_INET); - if (err) { - warning("ua: network init failed: %m\n", err); - return err; - } - uag.use_udp = udp; uag.use_tcp = tcp; uag.use_tls = tls; @@ -1338,14 +1338,14 @@ int ua_init(const char *software, bool udp, bool tcp, bool tls, list_init(&uag.ual); - err = sip_alloc(&uag.sip, net_dnsc(), bsize, bsize, bsize, + err = sip_alloc(&uag.sip, net_dnsc(net), bsize, bsize, bsize, software, exit_handler, NULL); if (err) { warning("ua: sip stack failed: %m\n", err); goto out; } - err = ua_add_transp(); + err = ua_add_transp(net); if (err) goto out; @@ -1367,7 +1367,7 @@ int ua_init(const char *software, bool udp, bool tcp, bool tls, if (err) goto out; - net_change(60, net_change_handler, NULL); + net_change(net, 60, net_change_handler, NULL); out: if (err) { @@ -1384,7 +1384,6 @@ int ua_init(const char *software, bool udp, bool tcp, bool tls, void ua_close(void) { cmd_unregister(cmdv); - net_close(); play_close(); ui_reset(); contact_close(); @@ -1482,14 +1481,15 @@ void uag_set_exit_handler(ua_exit_h *exith, void *arg) */ int uag_reset_transp(bool reg, bool reinvite) { + struct network *net = baresip_network(); struct le *le; int err; /* Update SIP transports */ sip_transp_flush(uag.sip); - (void)net_check(); - err = ua_add_transp(); + (void)net_check(net); + err = ua_add_transp(net); if (err) return err; diff --git a/test/main.c b/test/main.c index 42e381e..db99328 100644 --- a/test/main.c +++ b/test/main.c @@ -27,6 +27,7 @@ static const struct test tests[] = { TEST(test_cmd), TEST(test_cplusplus), TEST(test_mos), + TEST(test_network), TEST(test_ua_alloc), TEST(test_ua_register), TEST(test_ua_register_dns), @@ -182,6 +183,11 @@ int main(int argc, char *argv[]) err = ENOENT; goto out; } + + err = baresip_init(config, false); + if (err) + goto out; + str_ncpy(config->sip.local, "127.0.0.1:0", sizeof(config->sip.local)); uag_set_exit_handler(ua_exit_handler, NULL); @@ -228,6 +234,8 @@ int main(int argc, char *argv[]) ua_stop_all(true); ua_close(); + baresip_close(); + libre_close(); tmr_debug(); diff --git a/test/net.c b/test/net.c new file mode 100644 index 0000000..170fc3b --- /dev/null +++ b/test/net.c @@ -0,0 +1,46 @@ +/** + * @file test/net.c Baresip selftest -- networking + * + * Copyright (C) 2010 - 2016 Creytiv.com + */ +#include +#include +#include +#include "test.h" + + +static struct config_net default_config; + + +static void net_change_handler(void *arg) +{ + unsigned *count = arg; + ++*count; + info("network changed\n"); +} + + +int test_network(void) +{ + struct network *net = NULL; + unsigned change_count = 0; + int err; + + err = net_alloc(&net, &default_config, AF_INET); + TEST_ERR(err); + ASSERT_TRUE(net != NULL); + + ASSERT_EQ(AF_INET, net_af(net)); + + net_change(net, 1, net_change_handler, &change_count); + + ASSERT_EQ(0, change_count); + + net_force_change(net); + + ASSERT_EQ(1, change_count); + + out: + mem_deref(net); + return err; +} diff --git a/test/srcs.mk b/test/srcs.mk index a68ff94..06b4482 100644 --- a/test/srcs.mk +++ b/test/srcs.mk @@ -13,6 +13,7 @@ TEST_SRCS += ua.c TEST_SRCS += cplusplus.c TEST_SRCS += call.c TEST_SRCS += mos.c +TEST_SRCS += net.c # diff --git a/test/test.h b/test/test.h index 87972f9..cd00514 100644 --- a/test/test.h +++ b/test/test.h @@ -94,6 +94,7 @@ int test_ua_register_dns(void); int test_ua_register_auth(void); int test_ua_register_auth_dns(void); int test_mos(void); +int test_network(void); int test_call_answer(void); int test_call_reject(void); diff --git a/test/ua.c b/test/ua.c index 0473da5..abebe0c 100644 --- a/test/ua.c +++ b/test/ua.c @@ -217,6 +217,7 @@ static int reg_dns(enum sip_transp tp) struct dns_server *dnssrv = NULL; struct test t; const char *domain = "test.invalid"; + struct network *net = baresip_network(); unsigned server_count = 1; char aor[256]; char srv[256]; @@ -235,7 +236,7 @@ static int reg_dns(enum sip_transp tp) info("| DNS-server on %J\n", &dnssrv->addr); /* NOTE: must be done before ua_init() */ - err = net_dnssrv_add(&dnssrv->addr); + err = net_use_nameserver(net, &dnssrv->addr); TEST_ERR(err); for (i=0; iaddr); /* NOTE: must be done before ua_init() */ - err = net_dnssrv_add(&dnssrv->addr); + err = net_use_nameserver(net, &dnssrv->addr); TEST_ERR(err); for (i=0; i