summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/TODO2
-rw-r--r--include/baresip.h34
-rw-r--r--modules/account/account.c2
-rw-r--r--modules/contact/contact.c2
-rw-r--r--modules/menu/menu.c8
-rw-r--r--modules/natbd/natbd.c8
-rw-r--r--modules/rst/rst.c3
-rw-r--r--src/baresip.c51
-rw-r--r--src/call.c9
-rw-r--r--src/config.c15
-rw-r--r--src/core.h7
-rw-r--r--src/main.c12
-rw-r--r--src/net.c324
-rw-r--r--src/srcs.mk1
-rw-r--r--src/ua.c38
-rw-r--r--test/main.c8
-rw-r--r--test/net.c46
-rw-r--r--test/srcs.mk1
-rw-r--r--test/test.h1
-rw-r--r--test/ua.c6
20 files changed, 400 insertions, 178 deletions
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 <re.h>
+#include <baresip.h>
+#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
@@ -235,13 +235,6 @@ 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 <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;
}
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 <string.h>
+#include <re.h>
+#include <baresip.h>
+#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; i<server_count; i++) {
@@ -443,6 +444,7 @@ int test_ua_register_auth(void)
static int reg_auth_dns(enum sip_transp tp)
{
+ struct network *net = baresip_network();
struct dns_server *dnssrv = NULL;
struct test t;
const char *username = "alfredh";
@@ -466,7 +468,7 @@ static int reg_auth_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; i<server_count; i++) {