1
0
Fork 0
mirror of https://gitlab.gnome.org/GNOME/calls.git synced 2024-07-04 16:09:29 +00:00

sip: origin: Use CallsCredentials and adapt to changes

All parts not related to credentials are now being set when creating the nua
handles and then updated with nua_set_params() when the credentials get updated.
This commit is contained in:
Evangelos Ribeiro Tzaras 2021-04-28 00:26:10 +02:00
parent 3f72d34c49
commit 5d0de3d299
5 changed files with 272 additions and 281 deletions

View file

@ -25,6 +25,7 @@
#define G_LOG_DOMAIN "CallsSipOrigin" #define G_LOG_DOMAIN "CallsSipOrigin"
#include "calls-credentials.h"
#include "calls-message-source.h" #include "calls-message-source.h"
#include "calls-origin.h" #include "calls-origin.h"
#include "calls-sip-call.h" #include "calls-sip-call.h"
@ -55,14 +56,9 @@
enum { enum {
PROP_0, PROP_0,
PROP_ACC_CREDENTIALS,
PROP_NAME, PROP_NAME,
PROP_ACC_USER,
PROP_ACC_PASSWORD,
PROP_ACC_HOST,
PROP_ACC_PORT,
PROP_ACC_PROTOCOL,
PROP_ACC_DIRECT, PROP_ACC_DIRECT,
PROP_ACC_AUTO_CONNECT,
PROP_SIP_CONTEXT, PROP_SIP_CONTEXT,
PROP_SIP_LOCAL_PORT, PROP_SIP_LOCAL_PORT,
PROP_ACC_STATE, PROP_ACC_STATE,
@ -75,15 +71,10 @@ static GParamSpec *props[PROP_LAST_PROP];
struct _CallsSipOrigin struct _CallsSipOrigin
{ {
GObject parent_instance; GObject parent_instance;
GString *name;
CallsSipContext *ctx; CallsSipContext *ctx;
nua_t *nua; nua_t *nua;
CallsSipHandles *oper; CallsSipHandles *oper;
/* Maybe it makes sense to have one call handle (nua_handle_t) in
* CallsSipCall (do we need a backpointer to CallsSipOrigin?)
* and define the HMAGIC as a CallsSipOrigin
*/
/* Direct connection mode is useful for debugging purposes */ /* Direct connection mode is useful for debugging purposes */
gboolean use_direct_connection; gboolean use_direct_connection;
@ -95,15 +86,9 @@ struct _CallsSipOrigin
CallsSipMediaManager *media_manager; CallsSipMediaManager *media_manager;
gboolean auto_connect;
/* Account information */ /* Account information */
gchar *user; CallsCredentials *credentials;
gchar *password;
gchar *host;
gchar *transport_protocol;
const gchar *protocol_prefix; const gchar *protocol_prefix;
gint port;
gint local_port; gint local_port;
GList *calls; GList *calls;
@ -290,15 +275,99 @@ create_inbound (CallsSipOrigin *self,
add_call (self, address, TRUE, handle); add_call (self, address, TRUE, handle);
} }
static void
update_nua (CallsSipOrigin *self)
{
gboolean use_sips = FALSE;
gboolean use_ipv6 = FALSE; /* TODO make configurable or use DNS to figure out if ipv6 is supported*/
gchar *ipv6_bind = "*";
gchar *ipv4_bind = "0.0.0.0";
g_autofree gchar *sip_url = NULL;
g_autofree gchar *sips_url = NULL;
g_autofree char *user = NULL;
g_autofree char *host = NULL;
g_autofree gchar *address = NULL;
g_assert (CALLS_IS_SIP_ORIGIN (self));
g_assert (self->nua);
g_object_get (self->credentials,
"user", &user,
"host", &host,
NULL);
if (user && host) {
address = g_strconcat (self->protocol_prefix, ":", user, "@", host, NULL);
use_sips = check_sips (address);
use_ipv6 = check_ipv6 (host);
}
if (self->local_port > 0) {
sip_url = g_strdup_printf ("sip:%s:%d",
use_ipv6 ? ipv6_bind : ipv4_bind,
self->local_port);
sips_url = g_strdup_printf ("sips:%s:%d",
use_ipv6 ? ipv6_bind : ipv4_bind,
self->local_port);
} else {
sip_url = g_strdup_printf ("sip:%s:*",
use_ipv6 ? ipv6_bind : ipv4_bind);
sips_url = g_strdup_printf ("sips:%s:*",
use_ipv6 ? ipv6_bind : ipv4_bind);
}
nua_set_params (self->nua,
NUTAG_URL (sip_url),
TAG_IF (use_sips, NUTAG_SIPS_URL (sips_url)),
TAG_IF (address, SIPTAG_FROM_STR (address)),
TAG_NULL ());
}
static void static void
sip_authenticate (CallsSipOrigin *origin, update_credentials (CallsSipOrigin *self)
{
g_autofree char *protocol = NULL;
g_assert (CALLS_IS_SIP_ORIGIN (self));
g_debug ("Updating credentials");
g_object_get (self->credentials,
"protocol", &protocol,
NULL);
if (protocol == NULL) {
g_debug ("Protocol not set, falling back to 'UDP'");
g_object_set (self->credentials, "protocol", "UDP", NULL);
self->protocol_prefix = get_protocol_prefix ("UDP");
} else if (!protocol_is_valid (protocol)) {
g_warning ("Tried setting invalid protocol: '%s'\n"
"Falling back to default: '%s'",
protocol, "UDP");
g_object_set (self->credentials, "protocol", "UDP", NULL);
self->protocol_prefix = get_protocol_prefix ("UDP");
} else {
self->protocol_prefix = get_protocol_prefix (protocol);
}
if (self->nua)
update_nua (self);
}
static void
sip_authenticate (CallsSipOrigin *self,
nua_handle_t *nh, nua_handle_t *nh,
sip_t const *sip) sip_t const *sip)
{ {
const gchar *scheme = NULL; const gchar *scheme = NULL;
const gchar *realm = NULL; const gchar *realm = NULL;
g_autofree gchar *auth = NULL; g_autofree gchar *auth = NULL;
g_autofree char *user = NULL;
g_autofree char *password = NULL;
sip_www_authenticate_t *www_auth = sip->sip_www_authenticate; sip_www_authenticate_t *www_auth = sip->sip_www_authenticate;
sip_proxy_authenticate_t *proxy_auth = sip->sip_proxy_authenticate; sip_proxy_authenticate_t *proxy_auth = sip->sip_proxy_authenticate;
@ -316,8 +385,16 @@ sip_authenticate (CallsSipOrigin *origin,
} }
g_debug ("need to authenticate to realm %s", realm); g_debug ("need to authenticate to realm %s", realm);
g_object_get (self->credentials,
"user", &user,
"password", &password,
NULL);
/* TODO handle authentication to different realms
* https://source.puri.sm/Librem5/calls/-/issues/266
*/
auth = g_strdup_printf ("%s:%s:%s:%s", auth = g_strdup_printf ("%s:%s:%s:%s",
scheme, realm, origin->user, origin->password); scheme, realm, user, password);
nua_authenticate (nh, NUTAG_AUTH (auth), TAG_END ()); nua_authenticate (nh, NUTAG_AUTH (auth), TAG_END ());
} }
@ -449,7 +526,6 @@ sip_i_state (int status,
r_sdp->sdp_media->m_port + 1); r_sdp->sdp_media->m_port + 1);
} }
/* TODO use CallCallStates with g_object_set (notify!) */
switch (call_state) { switch (call_state) {
case nua_callstate_init: case nua_callstate_init:
return; return;
@ -636,7 +712,7 @@ setup_nua (CallsSipOrigin *self)
{ {
g_autofree gchar *address = NULL; g_autofree gchar *address = NULL;
nua_t *nua; nua_t *nua;
gboolean use_sips; gboolean use_sips = FALSE;
gboolean use_ipv6 = FALSE; /* TODO make configurable or use DNS to figure out if ipv6 is supported*/ gboolean use_ipv6 = FALSE; /* TODO make configurable or use DNS to figure out if ipv6 is supported*/
gchar *ipv6_bind = "*"; gchar *ipv6_bind = "*";
gchar *ipv4_bind = "0.0.0.0"; gchar *ipv4_bind = "0.0.0.0";
@ -644,15 +720,23 @@ setup_nua (CallsSipOrigin *self)
g_autofree gchar *sips_url = NULL; g_autofree gchar *sips_url = NULL;
const gchar *uuid = NULL; const gchar *uuid = NULL;
g_autofree gchar* urn_uuid = NULL; g_autofree gchar* urn_uuid = NULL;
g_autofree char *user = NULL;
g_autofree char *host = NULL;
uuid = nua_generate_instance_identifier (self->ctx->home); uuid = nua_generate_instance_identifier (self->ctx->home);
urn_uuid = g_strdup_printf ("urn:uuid:%s", uuid); urn_uuid = g_strdup_printf ("urn:uuid:%s", uuid);
address = g_strconcat (self->protocol_prefix, ":", self->user, "@", self->host, NULL); g_object_get (self->credentials,
"user", &user,
"host", &host,
NULL);
if (user && host) {
address = g_strconcat (self->protocol_prefix, ":", user, "@", host, NULL);
use_sips = check_sips (address); use_sips = check_sips (address);
use_ipv6 = check_ipv6 (self->host); use_ipv6 = check_ipv6 (host);
}
if (self->local_port > 0) { if (self->local_port > 0) {
sip_url = g_strdup_printf ("sip:%s:%d", sip_url = g_strdup_printf ("sip:%s:%d",
@ -674,8 +758,9 @@ setup_nua (CallsSipOrigin *self)
NUTAG_USER_AGENT (APP_DATA_NAME), NUTAG_USER_AGENT (APP_DATA_NAME),
NUTAG_URL (sip_url), NUTAG_URL (sip_url),
TAG_IF (use_sips, NUTAG_SIPS_URL (sips_url)), TAG_IF (use_sips, NUTAG_SIPS_URL (sips_url)),
SIPTAG_FROM_STR (address), TAG_IF (address, SIPTAG_FROM_STR (address)),
NUTAG_ALLOW ("INVITE, ACK, BYE, CANCEL, OPTIONS, UPDATE"), NUTAG_ALLOW ("INVITE, ACK, BYE, CANCEL, OPTIONS, UPDATE"),
NUTAG_SUPPORTED ("replaces, gruu, outbound"),
NTATAG_MAX_FORWARDS (70), NTATAG_MAX_FORWARDS (70),
NUTAG_ENABLEINVITE (1), NUTAG_ENABLEINVITE (1),
NUTAG_AUTOANSWER (0), NUTAG_AUTOANSWER (0),
@ -685,13 +770,31 @@ setup_nua (CallsSipOrigin *self)
NUTAG_INSTANCE (urn_uuid), NUTAG_INSTANCE (urn_uuid),
TAG_NULL ()); TAG_NULL ());
nua_set_params (nua,
NUTAG_SUPPORTED ("replaces, gruu, outbound"),
TAG_END ());
return nua; return nua;
} }
static char *
get_registrar_url (CallsSipOrigin *self)
{
char *registrar_url = NULL;
g_autofree char *host = NULL;
gint port;
g_assert (CALLS_IS_SIP_ORIGIN (self));
g_object_get (self->credentials,
"host", &host,
"port", &port,
NULL);
if (port > 0 && port <= 65535)
registrar_url =
g_strdup_printf ("%s:%s:%d", self->protocol_prefix, host, port);
else
registrar_url = g_strconcat (self->protocol_prefix, ":", host, NULL);
return registrar_url;
}
static CallsSipHandles * static CallsSipHandles *
setup_sip_handles (CallsSipOrigin *self) setup_sip_handles (CallsSipOrigin *self)
@ -706,10 +809,13 @@ setup_sip_handles (CallsSipOrigin *self)
return NULL; return NULL;
} }
registrar_url = g_strconcat (self->protocol_prefix, ":", self->host, NULL);
oper->context = self->ctx; oper->context = self->ctx;
oper->register_handle = nua_handle (self->nua, self->oper, oper->register_handle = nua_handle (self->nua, self->oper,
NUTAG_REGISTRAR (registrar_url), SIPTAG_EXPIRES_STR ("180"),
NUTAG_SUPPORTED ("replaces, outbound, gruu"),
NUTAG_OUTBOUND ("outbound natify gruuize validate"), // <- janus uses "no-validate"
NUTAG_M_PARAMS ("user=phone"),
NUTAG_CALLEE_CAPS (1), /* header parameters based on SDP capabilities and Allow header */
TAG_END ()); TAG_END ());
oper->call_handle = NULL; oper->call_handle = NULL;
return oper; return oper;
@ -719,42 +825,53 @@ setup_sip_handles (CallsSipOrigin *self)
static void static void
setup_account_for_direct_connection (CallsSipOrigin *self) setup_account_for_direct_connection (CallsSipOrigin *self)
{ {
g_autofree char *user = NULL;
g_assert (CALLS_IS_SIP_ORIGIN (self)); g_assert (CALLS_IS_SIP_ORIGIN (self));
g_object_get (self->credentials, "user", &user, NULL);
/* honour username, if previously set */ /* honour username, if previously set */
if (self->user == NULL) if (user == NULL)
self->user = g_strdup (g_get_user_name ()); g_object_set (self->credentials,
"user", g_get_user_name (),
NULL);
g_free (self->host); g_object_set (self->credentials,
self->host = g_strdup (g_get_host_name ()); "host", g_get_host_name (),
"password", NULL,
"protocol", "UDP",
NULL);
g_free (self->password); self->protocol_prefix = get_protocol_prefix ("UDP");
self->password = NULL;
g_free (self->transport_protocol); g_debug ("Account changed:\nuser: %s\nhost URL: %s",
self->transport_protocol = g_strdup ("UDP"); user ?: g_get_user_name (), g_get_host_name ());
self->protocol_prefix = get_protocol_prefix (self->transport_protocol);
g_debug ("Notifying account changed:\n"
"user: %s\nhost URL: %s", self->user, self->host);
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACC_USER]);
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACC_HOST]);
} }
static gboolean static gboolean
is_account_complete (CallsSipOrigin *self) is_account_complete (CallsSipOrigin *self)
{ {
g_autofree char *host = NULL;
g_autofree char *user = NULL;
g_autofree char *password = NULL;
g_autofree char *protocol = NULL;
g_assert (CALLS_IS_SIP_ORIGIN (self)); g_assert (CALLS_IS_SIP_ORIGIN (self));
g_object_get (self->credentials,
"host", &host,
"user", &user,
"password", &password,
"protocol", &protocol,
NULL);
/* we need only need to check for password if needing to authenticate over a proxy/UAS */ /* we need only need to check for password if needing to authenticate over a proxy/UAS */
if (self->user == NULL || if (user == NULL ||
(!self->use_direct_connection && self->password == NULL) || (!self->use_direct_connection && password == NULL) ||
self->host == NULL || host == NULL ||
self->transport_protocol == NULL || protocol == NULL)
self->protocol_prefix == NULL)
return FALSE; return FALSE;
return TRUE; return TRUE;
@ -766,6 +883,7 @@ init_sip_account (CallsSipOrigin *self,
GError **error) GError **error)
{ {
gboolean recoverable = FALSE; gboolean recoverable = FALSE;
gboolean auto_connect = FALSE;
if (self->use_direct_connection) { if (self->use_direct_connection) {
g_debug ("Direct connection case. Using user and hostname"); g_debug ("Direct connection case. Using user and hostname");
@ -802,8 +920,9 @@ init_sip_account (CallsSipOrigin *self,
else { else {
self->state = SIP_ACCOUNT_OFFLINE; self->state = SIP_ACCOUNT_OFFLINE;
if (self->auto_connect) g_object_get (self->credentials, "auto-connect", &auto_connect, NULL);
/* try to go online */ /* try to go online */
if (auto_connect)
calls_sip_origin_go_online (self, TRUE); calls_sip_origin_go_online (self, TRUE);
} }
@ -826,37 +945,9 @@ calls_sip_origin_set_property (GObject *object,
CallsSipOrigin *self = CALLS_SIP_ORIGIN (object); CallsSipOrigin *self = CALLS_SIP_ORIGIN (object);
switch (property_id) { switch (property_id) {
case PROP_ACC_CREDENTIALS:
case PROP_ACC_USER: self->credentials = g_value_get_object (value);
g_free (self->user); update_credentials (self);
self->user = g_value_dup_string (value);
break;
case PROP_ACC_PASSWORD:
g_free (self->password);
self->password = g_value_dup_string (value);
break;
case PROP_ACC_HOST:
g_free (self->host);
self->host = g_value_dup_string (value);
break;
case PROP_ACC_PORT:
self->port = g_value_get_int (value);
break;
case PROP_ACC_PROTOCOL:
if (!protocol_is_valid (g_value_get_string (value))) {
g_warning ("Tried setting invalid protocol: '%s'\n"
"Continue using old protocol: '%s'",
g_value_get_string (value), self->transport_protocol);
return;
}
g_free (self->transport_protocol);
self->transport_protocol = g_value_dup_string (value);
self->protocol_prefix = get_protocol_prefix (self->transport_protocol);
break; break;
case PROP_ACC_DIRECT: case PROP_ACC_DIRECT:
@ -871,10 +962,6 @@ calls_sip_origin_set_property (GObject *object,
g_warning ("Setting the account state does not yet have any effect"); g_warning ("Setting the account state does not yet have any effect");
break; break;
case PROP_ACC_AUTO_CONNECT:
self->auto_connect = g_value_get_boolean (value);
break;
case PROP_SIP_LOCAL_PORT: case PROP_SIP_LOCAL_PORT:
if (g_value_get_int (value) > 0 && g_value_get_int (value) < 1025) { if (g_value_get_int (value) > 0 && g_value_get_int (value) < 1025) {
g_warning ("Tried setting a privileged port as the local port to bind to: %d\n" g_warning ("Tried setting a privileged port as the local port to bind to: %d\n"
@ -899,40 +986,22 @@ calls_sip_origin_get_property (GObject *object,
GParamSpec *pspec) GParamSpec *pspec)
{ {
CallsSipOrigin *self = CALLS_SIP_ORIGIN (object); CallsSipOrigin *self = CALLS_SIP_ORIGIN (object);
g_autofree char *name = NULL;
switch (property_id) { switch (property_id) {
case PROP_NAME: case PROP_NAME:
g_value_set_string (value, self->name->str); g_object_get (self->credentials, "name", &name, NULL);
g_value_set_string (value, name);
break; break;
case PROP_CALLS: case PROP_CALLS:
g_value_set_pointer (value, g_list_copy (self->calls)); g_value_set_pointer (value, g_list_copy (self->calls));
break; break;
case PROP_ACC_USER:
g_value_set_string (value, self->user);
break;
case PROP_ACC_HOST:
g_value_set_string (value, self->host);
break;
case PROP_ACC_PORT:
g_value_set_int (value, self->port);
break;
case PROP_ACC_PROTOCOL:
g_value_set_string (value, self->transport_protocol);
break;
case PROP_ACC_STATE: case PROP_ACC_STATE:
g_value_set_enum (value, self->state); g_value_set_enum (value, self->state);
break; break;
case PROP_ACC_AUTO_CONNECT:
g_value_set_boolean (value, self->auto_connect);
break;
case PROP_SIP_LOCAL_PORT: case PROP_SIP_LOCAL_PORT:
g_value_set_int (value, self->local_port); g_value_set_int (value, self->local_port);
break; break;
@ -960,6 +1029,9 @@ calls_sip_origin_constructed (GObject *object)
self->media_manager = calls_sip_media_manager_default (); self->media_manager = calls_sip_media_manager_default ();
g_signal_connect_swapped (self->credentials, "account-updated",
(GCallback) update_credentials, self);
G_OBJECT_CLASS (calls_sip_origin_parent_class)->constructed (object); G_OBJECT_CLASS (calls_sip_origin_parent_class)->constructed (object);
} }
@ -1005,11 +1077,7 @@ calls_sip_origin_finalize (GObject *object)
{ {
CallsSipOrigin *self = CALLS_SIP_ORIGIN (object); CallsSipOrigin *self = CALLS_SIP_ORIGIN (object);
g_string_free (self->name, TRUE); g_object_unref (self->credentials);
g_free (self->user);
g_free (self->password);
g_free (self->host);
g_free (self->transport_protocol);
g_hash_table_destroy (self->call_handles); g_hash_table_destroy (self->call_handles);
G_OBJECT_CLASS (calls_sip_origin_parent_class)->finalize (object); G_OBJECT_CLASS (calls_sip_origin_parent_class)->finalize (object);
@ -1027,45 +1095,14 @@ calls_sip_origin_class_init (CallsSipOriginClass *klass)
object_class->get_property = calls_sip_origin_get_property; object_class->get_property = calls_sip_origin_get_property;
object_class->set_property = calls_sip_origin_set_property; object_class->set_property = calls_sip_origin_set_property;
props[PROP_ACC_USER] = props[PROP_ACC_CREDENTIALS] =
g_param_spec_string ("user", g_param_spec_object ("credentials",
"User", "Credentials",
"The username for authentication", "The credentials for this origin",
"", CALLS_TYPE_CREDENTIALS,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT); G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class, PROP_ACC_USER, props[PROP_ACC_USER]); g_object_class_install_property (object_class, PROP_ACC_CREDENTIALS, props[PROP_ACC_CREDENTIALS]);
props[PROP_ACC_PASSWORD] =
g_param_spec_string ("password",
"Password",
"The password for authentication",
"",
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT);
g_object_class_install_property (object_class, PROP_ACC_PASSWORD, props[PROP_ACC_PASSWORD]);
props[PROP_ACC_HOST] =
g_param_spec_string ("host",
"Host",
"The fqdn of the SIP server",
"",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
g_object_class_install_property (object_class, PROP_ACC_HOST, props[PROP_ACC_HOST]);
props[PROP_ACC_PORT] =
g_param_spec_int ("port",
"Port",
"Port of the SIP server",
1025, 65535, 5060,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
g_object_class_install_property (object_class, PROP_ACC_PORT, props[PROP_ACC_PORT]);
props[PROP_ACC_PROTOCOL] =
g_param_spec_string ("protocol",
"Protocol",
"The protocol used to connect to the SIP server",
"UDP",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
g_object_class_install_property (object_class, PROP_ACC_PROTOCOL, props[PROP_ACC_PROTOCOL]);
props[PROP_ACC_DIRECT] = props[PROP_ACC_DIRECT] =
g_param_spec_boolean ("direct-connection", g_param_spec_boolean ("direct-connection",
"Direct connection", "Direct connection",
@ -1098,14 +1135,6 @@ calls_sip_origin_class_init (CallsSipOriginClass *klass)
G_PARAM_READWRITE); G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_ACC_STATE, props[PROP_ACC_STATE]); g_object_class_install_property (object_class, PROP_ACC_STATE, props[PROP_ACC_STATE]);
props[PROP_ACC_AUTO_CONNECT] =
g_param_spec_boolean ("auto-connect",
"Auto connect",
"Automatically try to connect",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class, PROP_ACC_AUTO_CONNECT, props[PROP_ACC_AUTO_CONNECT]);
#define IMPLEMENTS(ID, NAME) \ #define IMPLEMENTS(ID, NAME) \
g_object_class_override_property (object_class, ID, NAME); \ g_object_class_override_property (object_class, ID, NAME); \
props[ID] = g_object_class_find_property(object_class, NAME); props[ID] = g_object_class_find_property(object_class, NAME);
@ -1134,42 +1163,24 @@ calls_sip_origin_origin_interface_init (CallsOriginInterface *iface)
static void static void
calls_sip_origin_init (CallsSipOrigin *self) calls_sip_origin_init (CallsSipOrigin *self)
{ {
self->name = g_string_new (NULL);
self->call_handles = g_hash_table_new (NULL, NULL); self->call_handles = g_hash_table_new (NULL, NULL);
} }
CallsSipOrigin * CallsSipOrigin *
calls_sip_origin_new (const gchar *name, calls_sip_origin_new (CallsSipContext *sip_context,
CallsSipContext *sip_context, CallsCredentials *credentials,
const gchar *user,
const gchar *password,
const gchar *host,
gint port,
gint local_port, gint local_port,
const gchar *protocol, gboolean direct_connection)
gboolean direct_connection,
gboolean auto_connect)
{ {
CallsSipOrigin *origin; g_return_val_if_fail (sip_context, NULL);
g_return_val_if_fail (credentials, NULL);
g_return_val_if_fail (sip_context != NULL, NULL); return g_object_new (CALLS_TYPE_SIP_ORIGIN,
origin = g_object_new (CALLS_TYPE_SIP_ORIGIN,
"sip-context", sip_context, "sip-context", sip_context,
"user", user, "credentials", g_object_ref (credentials),
"password", password,
"host", host,
"port", port,
"local-port", local_port, "local-port", local_port,
"protocol", protocol,
"direct-connection", direct_connection, "direct-connection", direct_connection,
"auto-connect", auto_connect,
NULL); NULL);
g_string_assign (origin->name, name);
return origin;
} }
@ -1185,16 +1196,24 @@ calls_sip_origin_go_online (CallsSipOrigin *self,
g_return_if_fail (CALLS_IS_SIP_ORIGIN (self)); g_return_if_fail (CALLS_IS_SIP_ORIGIN (self));
if (online) { if (online) {
g_autofree char *user = NULL;
g_autofree char *display_name = NULL;
g_autofree char *registrar_url = NULL;
if (self->state == SIP_ACCOUNT_ONLINE) if (self->state == SIP_ACCOUNT_ONLINE)
return; return;
g_object_get (self->credentials,
"user", &user,
"display-name", &display_name,
NULL);
registrar_url = get_registrar_url (self);
nua_register (self->oper->register_handle, nua_register (self->oper->register_handle,
SIPTAG_EXPIRES_STR ("180"), NUTAG_M_USERNAME (user),
NUTAG_SUPPORTED ("replaces, outbound, gruu"), TAG_IF (display_name, NUTAG_M_DISPLAY (display_name)),
NUTAG_OUTBOUND ("outbound natify gruuize validate"), // <- janus uses "no-validate" NUTAG_REGISTRAR (registrar_url),
NUTAG_M_USERNAME (self->user),
NUTAG_M_PARAMS ("user=phone"),
NUTAG_CALLEE_CAPS (1), /* header parameters based on SDP capabilities and Allow header */
TAG_END ()); TAG_END ());
} }
else { else {

View file

@ -24,6 +24,7 @@
#pragma once #pragma once
#include "calls-credentials.h"
#include "calls-sip-util.h" #include "calls-sip-util.h"
#include <glib-object.h> #include <glib-object.h>
@ -34,16 +35,10 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (CallsSipOrigin, calls_sip_origin, CALLS, SIP_ORIGIN, GObject); G_DECLARE_FINAL_TYPE (CallsSipOrigin, calls_sip_origin, CALLS, SIP_ORIGIN, GObject);
CallsSipOrigin *calls_sip_origin_new (const gchar *name, CallsSipOrigin *calls_sip_origin_new (CallsSipContext *sip_context,
CallsSipContext *sip_context, CallsCredentials *credentials,
const gchar *user,
const gchar *password,
const gchar *host,
gint port,
gint local_port, gint local_port,
const gchar *protocol, gboolean direct_connection);
gboolean direct_connection,
gboolean auto_connect);
void calls_sip_origin_go_online (CallsSipOrigin *self, void calls_sip_origin_go_online (CallsSipOrigin *self,
gboolean online); gboolean online);
G_END_DECLS G_END_DECLS

View file

@ -94,44 +94,23 @@ calls_sip_provider_load_accounts (CallsSipProvider *self)
for (gsize i = 0; groups[i] != NULL; i++) { for (gsize i = 0; groups[i] != NULL; i++) {
g_autoptr (CallsCredentials) credentials = calls_credentials_new (); g_autoptr (CallsCredentials) credentials = calls_credentials_new ();
g_autofree gchar *user = NULL;
g_autofree gchar *password = NULL;
g_autofree gchar *host = NULL;
g_autofree gchar *protocol = NULL;
gint port = 0;
gint local_port = 0; gint local_port = 0;
gboolean auto_connect = TRUE;
gboolean direct_connection = gboolean direct_connection =
g_key_file_get_boolean (key_file, groups[i], "Direct", NULL); g_key_file_get_boolean (key_file, groups[i], "Direct", NULL);
if (direct_connection) { if (direct_connection) {
g_object_set (credentials, "name", groups[i], NULL);
local_port = g_key_file_get_integer (key_file, groups[i], "LocalPort", NULL); local_port = g_key_file_get_integer (key_file, groups[i], "LocalPort", NULL);
/* direct connection mode, needs a local port set */
if (local_port == 0) if (local_port == 0)
local_port = 5060; local_port = 5060;
protocol = g_strdup ("UDP"); } else {
goto skip;
}
calls_credentials_update_from_keyfile (credentials, key_file, groups[i]); calls_credentials_update_from_keyfile (credentials, key_file, groups[i]);
}
g_object_get (G_OBJECT (credentials),
"host", &host,
"user", &user,
"password", &password,
"port", &port,
"protocol", &protocol,
"auto-connect", &auto_connect,
NULL);
skip:
g_debug ("Adding origin for SIP account %s", groups[i]); g_debug ("Adding origin for SIP account %s", groups[i]);
calls_sip_provider_add_origin (self, g_steal_pointer (&credentials), local_port, direct_connection);
calls_sip_provider_add_origin (self, groups[i],
user, password,
host, port, local_port,
protocol,
direct_connection,
auto_connect);
} }
g_strfreev (groups); g_strfreev (groups);
@ -369,50 +348,29 @@ calls_sip_provider_init (CallsSipProvider *self)
/** /**
* calls_sip_provider_add_origin: * calls_sip_provider_add_origin:
* @self: A #CallsSipProvider * @self: A #CallsSipProvider
* @name: The name of the origin * @credentials: A #CallsCredentials
* @user: (nullable): The username to use or %NULL
* @password: (nullable): The password to use or %NULL
* @host: (nullable):The host to use or %NULL
* @port: The port of the host to connect to, usually 5060
* @local_port: The local port to bind to or 0 * @local_port: The local port to bind to or 0
* @protocol: (nullable): The protocol to use. Can be "TCP", "UDP", "TLS" or %NULL
* @direct_connection: %TRUE to use a direct connection to peers, %FALSE otherwise * @direct_connection: %TRUE to use a direct connection to peers, %FALSE otherwise
* @auto_connect: %TRUE to automatically try to register, %FALSE otherwise
* *
* Adds a new origin (SIP account). If @direct_connection is set the nullables * Adds a new origin (SIP account). If @direct_connection is set
* can be set automatically (f.e. use the local user and hostname). * some properties of @credentials can be set automatically
* (f.e. use the username and hostname).
*/ */
void void
calls_sip_provider_add_origin (CallsSipProvider *self, calls_sip_provider_add_origin (CallsSipProvider *self,
const gchar *name, CallsCredentials *credentials,
const gchar *user,
const gchar *password,
const gchar *host,
gint port,
gint local_port, gint local_port,
const gchar *protocol, gboolean direct_connection)
gboolean direct_connection,
gboolean auto_connect)
{ {
g_autoptr (CallsSipOrigin) origin = NULL; g_autoptr (CallsSipOrigin) origin = NULL;
g_return_if_fail (CALLS_IS_SIP_PROVIDER (self)); g_return_if_fail (CALLS_IS_SIP_PROVIDER (self));
g_return_if_fail (CALLS_IS_CREDENTIALS (credentials));
origin = calls_sip_origin_new (name, origin = calls_sip_origin_new (self->ctx,
self->ctx, credentials,
user,
password,
host,
port,
local_port, local_port,
protocol, direct_connection);
direct_connection,
auto_connect);
if (!origin) {
g_warning ("Could not create CallsSipOrigin");
return;
}
g_list_store_append (self->origins, origin); g_list_store_append (self->origins, origin);
} }

View file

@ -26,6 +26,7 @@
#include <glib-object.h> #include <glib-object.h>
#include "calls-credentials.h"
#include "calls-provider.h" #include "calls-provider.h"
G_BEGIN_DECLS G_BEGIN_DECLS
@ -36,14 +37,8 @@ G_DECLARE_FINAL_TYPE (CallsSipProvider, calls_sip_provider, CALLS, SIP_PROVIDER,
CallsSipProvider *calls_sip_provider_new (); CallsSipProvider *calls_sip_provider_new ();
void calls_sip_provider_add_origin (CallsSipProvider *self, void calls_sip_provider_add_origin (CallsSipProvider *self,
const gchar *name, CallsCredentials *credentials,
const gchar *user,
const gchar *password,
const gchar *host,
gint port,
gint local_port, gint local_port,
const gchar *protocol, gboolean direct_connection);
gboolean direct_connection,
gboolean auto_connect);
G_END_DECLS G_END_DECLS

View file

@ -23,6 +23,9 @@ typedef struct {
CallsSipOrigin *origin_alice; CallsSipOrigin *origin_alice;
CallsSipOrigin *origin_bob; CallsSipOrigin *origin_bob;
CallsSipOrigin *origin_offline; CallsSipOrigin *origin_offline;
CallsCredentials *credentials_alice;
CallsCredentials *credentials_bob;
CallsCredentials *credentials_offline;
} SipFixture; } SipFixture;
@ -358,27 +361,43 @@ setup_sip_origins (SipFixture *fixture,
gconstpointer user_data) gconstpointer user_data)
{ {
GListModel *origins; GListModel *origins;
CallsCredentials *alice = calls_credentials_new ();
CallsCredentials *bob = calls_credentials_new ();
CallsCredentials *offline = calls_credentials_new ();
setup_sip_provider (fixture, user_data); setup_sip_provider (fixture, user_data);
calls_sip_provider_add_origin (fixture->provider, "Alice", g_object_set (alice, "name", "Alice", "user", "alice", NULL);
"alice", NULL, NULL, 5060,
5060, "UDP", TRUE, FALSE);
calls_sip_provider_add_origin (fixture->provider, "Bob", calls_sip_provider_add_origin (fixture->provider, alice, 5060, TRUE);
"bob", NULL, NULL, 5060,
5061, "UDP", TRUE, FALSE);
calls_sip_provider_add_origin (fixture->provider, "Offline", g_object_set (bob, "name", "Bob", "user", "bob", NULL);
"someuser", "sip.imaginary-host.org", "password", 5060,
5062, "UDP", FALSE, FALSE); calls_sip_provider_add_origin (fixture->provider, bob, 5061, TRUE);
g_object_set (offline,
"name", "Offline",
"user", "someuser",
"host", "sip.imaginary-host.org",
"password", "password123",
"port", 5060,
"protocol", "UDP",
"auto-connect", FALSE,
NULL);
calls_sip_provider_add_origin (fixture->provider, offline, 0, FALSE);
origins = calls_provider_get_origins origins = calls_provider_get_origins
(CALLS_PROVIDER (fixture->provider)); (CALLS_PROVIDER (fixture->provider));
fixture->origin_alice = g_list_model_get_item (origins, 0); fixture->origin_alice = g_list_model_get_item (origins, 0);
fixture->credentials_alice = alice;
fixture->origin_bob = g_list_model_get_item (origins, 1); fixture->origin_bob = g_list_model_get_item (origins, 1);
fixture->credentials_bob = bob;
fixture->origin_offline = g_list_model_get_item (origins, 2); fixture->origin_offline = g_list_model_get_item (origins, 2);
fixture->credentials_offline = offline;
} }
static void static void
@ -386,8 +405,13 @@ tear_down_sip_origins (SipFixture *fixture,
gconstpointer user_data) gconstpointer user_data)
{ {
g_clear_object (&fixture->origin_alice); g_clear_object (&fixture->origin_alice);
g_clear_object (&fixture->credentials_alice);
g_clear_object (&fixture->origin_bob); g_clear_object (&fixture->origin_bob);
g_clear_object (&fixture->credentials_bob);
g_clear_object (&fixture->origin_offline); g_clear_object (&fixture->origin_offline);
g_clear_object (&fixture->credentials_offline);
tear_down_sip_provider (fixture, user_data); tear_down_sip_provider (fixture, user_data);
} }