diff --git a/plugins/provider/sip/calls-sip-account-widget.c b/plugins/provider/sip/calls-sip-account-widget.c index b83e48e..d87ee89 100644 --- a/plugins/provider/sip/calls-sip-account-widget.c +++ b/plugins/provider/sip/calls-sip-account-widget.c @@ -66,6 +66,7 @@ struct _CallsSipAccountWidget { /* widgets for editing account credentials */ AdwEntryRow *host; + AdwEntryRow *proxy; AdwEntryRow *display_name; AdwEntryRow *user; AdwEntryRow *password; @@ -350,6 +351,7 @@ clear_form (CallsSipAccountWidget *self) g_assert (CALLS_IS_SIP_ACCOUNT_WIDGET (self)); gtk_editable_set_text (GTK_EDITABLE (self->host), ""); + gtk_editable_set_text (GTK_EDITABLE (self->proxy), ""); gtk_editable_set_text (GTK_EDITABLE (self->display_name), ""); gtk_editable_set_text (GTK_EDITABLE (self->user), ""); gtk_editable_set_text (GTK_EDITABLE (self->password), ""); @@ -374,6 +376,7 @@ edit_form (CallsSipAccountWidget *self, CallsSipOrigin *origin) { g_autofree char *host = NULL; + g_autofree char *proxy = NULL; g_autofree char *display_name = NULL; g_autofree char *user = NULL; g_autofree char *password = NULL; @@ -399,6 +402,7 @@ edit_form (CallsSipAccountWidget *self, g_object_get (origin, "host", &host, + "proxy", &proxy, "display-name", &display_name, "user", &user, "password", &password, @@ -423,6 +427,7 @@ edit_form (CallsSipAccountWidget *self, /* set UI elements */ gtk_editable_set_text (GTK_EDITABLE (self->host), host); + gtk_editable_set_text (GTK_EDITABLE (self->proxy), proxy ?: ""); gtk_editable_set_text (GTK_EDITABLE (self->display_name), display_name ?: ""); gtk_editable_set_text (GTK_EDITABLE (self->user), user); gtk_editable_set_text (GTK_EDITABLE (self->password), password); @@ -452,6 +457,7 @@ on_login_clicked (CallsSipAccountWidget *self) origin = calls_sip_provider_add_origin (self->provider, id, gtk_editable_get_text (GTK_EDITABLE (self->host)), + gtk_editable_get_text (GTK_EDITABLE (self->proxy)), gtk_editable_get_text (GTK_EDITABLE (self->user)), gtk_editable_get_text (GTK_EDITABLE (self->password)), gtk_editable_get_text (GTK_EDITABLE (self->display_name)), @@ -486,6 +492,7 @@ on_apply_clicked (CallsSipAccountWidget *self) calls_sip_origin_set_credentials (self->origin, gtk_editable_get_text (GTK_EDITABLE (self->host)), + gtk_editable_get_text (GTK_EDITABLE (self->proxy)), gtk_editable_get_text (GTK_EDITABLE (self->user)), gtk_editable_get_text (GTK_EDITABLE (self->password)), gtk_editable_get_text (GTK_EDITABLE (self->display_name)), @@ -599,6 +606,7 @@ calls_sip_account_widget_class_init (CallsSipAccountWidgetClass *klass) gtk_widget_class_bind_template_child (widget_class, CallsSipAccountWidget, apply_btn); gtk_widget_class_bind_template_child (widget_class, CallsSipAccountWidget, host); + gtk_widget_class_bind_template_child (widget_class, CallsSipAccountWidget, proxy); gtk_widget_class_bind_template_child (widget_class, CallsSipAccountWidget, display_name); gtk_widget_class_bind_template_child (widget_class, CallsSipAccountWidget, user); gtk_widget_class_bind_template_child (widget_class, CallsSipAccountWidget, password); diff --git a/plugins/provider/sip/calls-sip-origin.c b/plugins/provider/sip/calls-sip-origin.c index 2c7e553..39a01af 100644 --- a/plugins/provider/sip/calls-sip-origin.c +++ b/plugins/provider/sip/calls-sip-origin.c @@ -65,6 +65,7 @@ enum { PROP_ID, PROP_EMERGENCY_NUMBERS, PROP_ACC_HOST, + PROP_ACC_PROXY, PROP_ACC_USER, PROP_ACC_PASSWORD, PROP_ACC_DISPLAY_NAME, @@ -107,6 +108,7 @@ struct _CallsSipOrigin { /* Account information */ char *host; + char *proxy; char *user; char *password; char *display_name; @@ -427,7 +429,7 @@ sip_authenticate (CallsSipOrigin *self, g_warning ("No authentication context found"); return; } - g_debug ("need to authenticate to realm %s", realm); + g_debug ("Authenticating to realm %s using %s", realm, www_auth ? "www_auth" : "proxy_auth"); /* TODO handle authentication to different realms * https://source.puri.sm/Librem5/calls/-/issues/266 @@ -953,6 +955,7 @@ setup_nua (CallsSipOrigin *self) g_autofree char *sip_url = NULL; g_autofree char *sips_url = NULL; g_autofree char *from_str = NULL; + g_autofree char *proxy_url = NULL; if (!sip_test_env || sip_test_env[0] == '\0') { CallsNetworkWatch *nw = calls_network_watch_get_default (); @@ -1000,12 +1003,15 @@ setup_nua (CallsSipOrigin *self) g_free (temp); } + proxy_url = g_strdup_printf ("%s:%s", self->protocol_prefix, self->proxy); + nua = nua_create (self->ctx->root, sip_callback, self, NUTAG_USER_AGENT (APP_DATA_NAME), NUTAG_URL (sip_url), TAG_IF (use_sips, NUTAG_SIPS_URL (sips_url)), + TAG_IF (!!self->proxy, NUTAG_PROXY (proxy_url)), SIPTAG_FROM_STR (from_str), NUTAG_ALLOW ("INVITE, ACK, BYE, CANCEL, OPTIONS, UPDATE"), NUTAG_SUPPORTED ("replaces, gruu, outbound"), @@ -1330,6 +1336,11 @@ calls_sip_origin_set_property (GObject *object, self->host = g_value_dup_string (value); break; + case PROP_ACC_PROXY: + g_free (self->proxy); + self->proxy = g_value_dup_string (value); + break; + case PROP_ACC_DISPLAY_NAME: g_free (self->display_name); self->display_name = g_value_dup_string (value); @@ -1416,6 +1427,10 @@ calls_sip_origin_get_property (GObject *object, g_value_set_string (value, self->host); break; + case PROP_ACC_PROXY: + g_value_set_string (value, self->proxy); + break; + case PROP_ACC_DISPLAY_NAME: g_value_set_string (value, self->display_name); break; @@ -1533,6 +1548,7 @@ calls_sip_origin_dispose (GObject *object) g_clear_pointer (&self->transport_protocol, g_free); g_clear_pointer (&self->display_name, g_free); g_clear_pointer (&self->host, g_free); + g_clear_pointer (&self->proxy, g_free); g_clear_pointer (&self->user, g_free); g_clear_pointer (&self->password, g_free); g_clear_pointer (&self->address, g_free); @@ -1571,6 +1587,14 @@ calls_sip_origin_class_init (CallsSipOriginClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ACC_HOST, props[PROP_ACC_HOST]); + props[PROP_ACC_PROXY] = + g_param_spec_string ("proxy", + "Proxy", + "The proxy to connect to", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_ACC_PROXY, props[PROP_ACC_PROXY]); + props[PROP_ACC_USER] = g_param_spec_string ("user", "User", @@ -1718,6 +1742,7 @@ calls_sip_origin_init (CallsSipOrigin *self) void calls_sip_origin_set_credentials (CallsSipOrigin *self, const char *host, + const char *proxy, const char *user, const char *password, const char *display_name, @@ -1744,6 +1769,9 @@ calls_sip_origin_set_credentials (CallsSipOrigin *self, g_free (self->host); self->host = g_strdup (host); + g_free (self->proxy); + self->proxy = g_strdup (proxy); + g_free (self->user); self->user = g_strdup (user); diff --git a/plugins/provider/sip/calls-sip-origin.h b/plugins/provider/sip/calls-sip-origin.h index faadfa7..0a00b97 100644 --- a/plugins/provider/sip/calls-sip-origin.h +++ b/plugins/provider/sip/calls-sip-origin.h @@ -36,6 +36,7 @@ G_DECLARE_FINAL_TYPE (CallsSipOrigin, calls_sip_origin, CALLS, SIP_ORIGIN, GObje void calls_sip_origin_set_credentials (CallsSipOrigin *self, const char *host, + const char *proxy, const char *user, const char *password, const char *display_name, diff --git a/plugins/provider/sip/calls-sip-provider.c b/plugins/provider/sip/calls-sip-provider.c index 8149f0c..f8bdf5a 100644 --- a/plugins/provider/sip/calls-sip-provider.c +++ b/plugins/provider/sip/calls-sip-provider.c @@ -120,6 +120,7 @@ on_origin_pw_looked_up (GObject *source, g_autoptr (GError) error = NULL; g_autofree char *id = NULL; g_autofree char *host = NULL; + g_autofree char *proxy = NULL; g_autofree char *user = NULL; g_autofree char *password = NULL; g_autofree char *display_name = NULL; @@ -143,6 +144,7 @@ on_origin_pw_looked_up (GObject *source, g_debug ("Password looked up for %s", id); host = g_key_file_get_string (data->key_file, data->name, "Host", NULL); + proxy = g_key_file_get_string (data->key_file, data->name, "Proxy", NULL); user = g_key_file_get_string (data->key_file, data->name, "User", NULL); display_name = g_key_file_get_string (data->key_file, data->name, "DisplayName", NULL); protocol = g_key_file_get_string (data->key_file, data->name, "Protocol", NULL); @@ -187,6 +189,7 @@ on_origin_pw_looked_up (GObject *source, calls_sip_provider_add_origin_full (data->provider, id, host, + proxy, user, password, display_name, @@ -207,6 +210,7 @@ new_origin_from_keyfile_secret (CallsSipProvider *self, const char *name) { g_autofree char *host = NULL; + g_autofree char *proxy = NULL; g_autofree char *user = NULL; SipOriginLoadData *data; @@ -220,6 +224,7 @@ new_origin_from_keyfile_secret (CallsSipProvider *self, } host = g_key_file_get_string (key_file, name, "Host", NULL); + proxy = g_key_file_get_string (key_file, name, "Proxy", NULL); user = g_key_file_get_string (key_file, name, "User", NULL); data = g_new0 (SipOriginLoadData, 1); @@ -254,12 +259,14 @@ static void origin_pw_delete_secret (CallsSipOrigin *origin) { g_autofree char *host = NULL; + g_autofree char *proxy = NULL; g_autofree char *user = NULL; g_assert (CALLS_IS_SIP_ORIGIN (origin)); g_object_get (origin, "host", &host, + "proxy", &proxy, "user", &user, NULL); @@ -292,6 +299,7 @@ origin_to_keyfile (CallsSipOrigin *origin, { g_autofree char *id = NULL; g_autofree char *host = NULL; + g_autofree char *proxy = NULL; g_autofree char *user = NULL; g_autofree char *password = NULL; g_autofree char *display_name = NULL; @@ -310,6 +318,7 @@ origin_to_keyfile (CallsSipOrigin *origin, g_object_get (origin, "id", &id, "host", &host, + "proxy", &proxy, "user", &user, "password", &password, "display-name", &display_name, @@ -324,6 +333,7 @@ origin_to_keyfile (CallsSipOrigin *origin, g_key_file_set_string (key_file, name, "Id", id); g_key_file_set_string (key_file, name, "Host", host); + g_key_file_set_string (key_file, name, "Proxy", proxy); g_key_file_set_string (key_file, name, "User", user); g_key_file_set_string (key_file, name, "DisplayName", display_name ?: ""); g_key_file_set_string (key_file, name, "Protocol", protocol); @@ -658,6 +668,7 @@ calls_sip_provider_init (CallsSipProvider *self) * @self: A #CallsSipProvider * @id: The id of the new origin (should be unique) * @host: The host to connect to + * @proxy: The proxy to connect to * @user: The username to use * @password: The password to use * @display_name: The display name @@ -674,6 +685,7 @@ CallsSipOrigin * calls_sip_provider_add_origin (CallsSipProvider *self, const char *id, const char *host, + const char *proxy, const char *user, const char *password, const char *display_name, @@ -685,6 +697,7 @@ calls_sip_provider_add_origin (CallsSipProvider *self, return calls_sip_provider_add_origin_full (self, id, host, + proxy, user, password, display_name, @@ -703,6 +716,7 @@ calls_sip_provider_add_origin (CallsSipProvider *self, * @self: A #CallsSipProvider * @id: The id of the new origin (should be unique) * @host: The host to connect to + * @proxy: The proxy to connect to * @user: The username to use * @password: The password to use * @display_name: The display name @@ -724,6 +738,7 @@ CallsSipOrigin * calls_sip_provider_add_origin_full (CallsSipProvider *self, const char *id, const char *host, + const char *proxy, const char *user, const char *password, const char *display_name, @@ -759,6 +774,7 @@ calls_sip_provider_add_origin_full (CallsSipProvider *self, "id", id, "sip-context", self->ctx, "host", host, + "proxy", proxy, "user", user, "password", password, "display-name", display_name, diff --git a/plugins/provider/sip/calls-sip-provider.h b/plugins/provider/sip/calls-sip-provider.h index a5343ae..1ca2c2c 100644 --- a/plugins/provider/sip/calls-sip-provider.h +++ b/plugins/provider/sip/calls-sip-provider.h @@ -40,6 +40,7 @@ CallsSipProvider *calls_sip_provider_new (void); CallsSipOrigin *calls_sip_provider_add_origin (CallsSipProvider *self, const char *id, const char *host, + const char *proxy, const char *user, const char *password, const char *display_name, @@ -50,6 +51,7 @@ CallsSipOrigin *calls_sip_provider_add_origin (CallsSipProvider *self, CallsSipOrigin *calls_sip_provider_add_origin_full (CallsSipProvider *self, const char *id, const char *host, + const char *proxy, const char *user, const char *password, const char *display_name, diff --git a/plugins/provider/sip/sip-account-widget.ui b/plugins/provider/sip/sip-account-widget.ui index ed483c8..067672e 100644 --- a/plugins/provider/sip/sip-account-widget.ui +++ b/plugins/provider/sip/sip-account-widget.ui @@ -59,6 +59,16 @@ + + + + + Proxy (Optional) + + + + + diff --git a/plugins/provider/tests/test-sip.c b/plugins/provider/tests/test-sip.c index 1c594ce..64a9d2d 100644 --- a/plugins/provider/tests/test-sip.c +++ b/plugins/provider/tests/test-sip.c @@ -82,6 +82,9 @@ test_sip_origin_objects (SipFixture *fixture, gconstpointer user_data) { CallsAccountState state_alice, state_bob, state_offline; + g_autofree gchar *proxy_alice = NULL; + g_autofree gchar *proxy_bob = NULL; + g_autofree gchar *proxy_offline = NULL; g_assert_true (G_IS_OBJECT (fixture->origin_alice)); g_assert_true (G_IS_OBJECT (fixture->origin_bob)); @@ -112,6 +115,20 @@ test_sip_origin_objects (SipFixture *fixture, g_assert_cmpint (state_alice, ==, CALLS_ACCOUNT_STATE_ONLINE); g_assert_cmpint (state_bob, ==, CALLS_ACCOUNT_STATE_ONLINE); g_assert_cmpint (state_offline, ==, CALLS_ACCOUNT_STATE_OFFLINE); + + g_object_get (fixture->origin_alice, + "proxy", &proxy_alice, + NULL); + g_object_get (fixture->origin_bob, + "proxy", &proxy_bob, + NULL); + g_object_get (fixture->origin_offline, + "proxy", &proxy_offline, + NULL); + + g_assert_null (proxy_alice); + g_assert_null (proxy_bob); + g_assert_cmpstr (proxy_offline, ==, "proxy.sip.imaginary-host.org"); } static void @@ -364,6 +381,7 @@ setup_sip_origins (SipFixture *fixture, calls_sip_provider_add_origin_full (fixture->provider, "sip1", NULL, + NULL, "alice", NULL, NULL, @@ -380,6 +398,7 @@ setup_sip_origins (SipFixture *fixture, calls_sip_provider_add_origin_full (fixture->provider, "sip2", NULL, + NULL, "bob", NULL, NULL, @@ -396,6 +415,7 @@ setup_sip_origins (SipFixture *fixture, calls_sip_provider_add_origin_full (fixture->provider, "sip3", "sip.imaginary-host.org", + "proxy.sip.imaginary-host.org", "username", "password", NULL,