summaryrefslogtreecommitdiff
path: root/src/sip-connection-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sip-connection-manager.c')
-rw-r--r--src/sip-connection-manager.c428
1 files changed, 19 insertions, 409 deletions
diff --git a/src/sip-connection-manager.c b/src/sip-connection-manager.c
index 7a33481..ecb882e 100644
--- a/src/sip-connection-manager.c
+++ b/src/sip-connection-manager.c
@@ -38,6 +38,7 @@
#include <tpsip/sofia-decls.h>
#include <sofia-sip/su_glib.h>
+#include "protocol.h"
#include "sip-connection-manager.h"
#include "sip-connection.h"
@@ -48,165 +49,6 @@
G_DEFINE_TYPE(TpsipConnectionManager, tpsip_connection_manager,
TP_TYPE_BASE_CONNECTION_MANAGER)
-/* private structure *//* typedef struct _TpsipConnectionManagerPrivate TpsipConnectionManagerPrivate; */
-
-typedef struct {
- gchar *account;
- gchar *auth_user;
- gchar *password;
- gchar *alias;
- gchar *registrar;
- gchar *proxy_host;
- guint port;
- gchar *transport;
- gboolean loose_routing;
- gboolean discover_binding;
- gchar *keepalive_mechanism;
- guint keepalive_interval;
- gboolean discover_stun;
- gchar *stun_server;
- guint stun_port;
- gboolean immutable_streams;
- gchar *local_ip_address;
- guint local_port;
- gchar *extra_auth_user;
- gchar *extra_auth_password;
-} TpsipConnParams;
-
-static void *
-alloc_params (void)
-{
- return g_slice_new0 (TpsipConnParams);
-}
-
-static void
-free_params (void *p)
-{
- TpsipConnParams *params = (TpsipConnParams *)p;
-
- g_free (params->account);
- g_free (params->auth_user);
- g_free (params->password);
- g_free (params->alias);
- g_free (params->registrar);
- g_free (params->proxy_host);
- g_free (params->transport);
- g_free (params->keepalive_mechanism);
- g_free (params->stun_server);
- g_free (params->local_ip_address);
- g_free (params->extra_auth_user);
- g_free (params->extra_auth_password);
-
- g_slice_free (TpsipConnParams, params);
-}
-
-enum {
- TPSIP_CONN_PARAM_ACCOUNT = 0,
- TPSIP_CONN_PARAM_AUTH_USER,
- TPSIP_CONN_PARAM_PASSWORD,
- TPSIP_CONN_PARAM_ALIAS,
- TPSIP_CONN_PARAM_REGISTRAR,
- TPSIP_CONN_PARAM_PROXY_HOST,
- TPSIP_CONN_PARAM_PORT,
- TPSIP_CONN_PARAM_TRANSPORT,
- TPSIP_CONN_PARAM_LOOSE_ROUTING,
- TPSIP_CONN_PARAM_DISCOVER_BINDING,
- TPSIP_CONN_PARAM_KEEPALIVE_MECHANISM,
- TPSIP_CONN_PARAM_KEEPALIVE_INTERVAL,
- TPSIP_CONN_PARAM_DISCOVER_STUN,
- TPSIP_CONN_PARAM_STUN_SERVER,
- TPSIP_CONN_PARAM_STUN_PORT,
- TPSIP_CONN_PARAM_IMMUTABLE_STREAMS,
- TPSIP_CONN_PARAM_LOCAL_IP_ADDRESS,
- TPSIP_CONN_PARAM_LOCAL_PORT,
- TPSIP_CONN_PARAM_EXTRA_AUTH_USER,
- TPSIP_CONN_PARAM_EXTRA_AUTH_PASSWORD,
- N_TPSIP_CONN_PARAMS
-};
-
-static const TpCMParamSpec tpsip_params[] = {
- /* Account (a sip: URI) */
- { "account", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- TP_CONN_MGR_PARAM_FLAG_REQUIRED | TP_CONN_MGR_PARAM_FLAG_REGISTER,
- NULL, G_STRUCT_OFFSET (TpsipConnParams, account) },
- /* Username to register with, if different than in the account URI */
- { "auth-user", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- 0, NULL, G_STRUCT_OFFSET (TpsipConnParams, auth_user) },
- /* Password */
- { "password", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- TP_CONN_MGR_PARAM_FLAG_SECRET,
- NULL, G_STRUCT_OFFSET (TpsipConnParams, password) },
- /* Display name for self */
- { "alias", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL,
- G_STRUCT_OFFSET(TpsipConnParams, alias),
- /* setting a 0-length alias makes no sense */
- tp_cm_param_filter_string_nonempty, NULL },
- /* Registrar */
- { "registrar", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- 0, NULL, G_STRUCT_OFFSET (TpsipConnParams, registrar) },
- /* Used to compose proxy URI */
- { "proxy-host", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- 0, NULL, G_STRUCT_OFFSET (TpsipConnParams, proxy_host) },
- /* Used to compose proxy URI */
- { "port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(SIP_DEFAULT_PORT),
- G_STRUCT_OFFSET (TpsipConnParams, port) },
- /* Used to compose proxy URI */
- { "transport", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, "auto",
- G_STRUCT_OFFSET (TpsipConnParams, transport) },
- /* Enables loose routing as per RFC 3261 */
- { "loose-routing", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(FALSE),
- G_STRUCT_OFFSET (TpsipConnParams, loose_routing) },
- /* Used to enable proactive NAT traversal techniques */
- { "discover-binding", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(TRUE),
- G_STRUCT_OFFSET (TpsipConnParams, discover_binding) },
- /* Mechanism used for connection keepalive maintenance */
- { "keepalive-mechanism", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, "auto",
- G_STRUCT_OFFSET (TpsipConnParams, keepalive_mechanism) },
- /* Keep-alive interval */
- { "keepalive-interval", DBUS_TYPE_UINT32_AS_STRING, G_TYPE_UINT,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(0),
- G_STRUCT_OFFSET (TpsipConnParams, keepalive_interval) },
- /* Use SRV DNS lookup to discover STUN server */
- { "discover-stun", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(TRUE),
- G_STRUCT_OFFSET (TpsipConnParams, discover_stun) },
- /* STUN server */
- { "stun-server", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- 0, NULL, G_STRUCT_OFFSET (TpsipConnParams, stun_server) },
- /* STUN port */
- { "stun-port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT,
- GUINT_TO_POINTER(TPSIP_DEFAULT_STUN_PORT),
- G_STRUCT_OFFSET (TpsipConnParams, stun_port) },
- /* If the session content cannot be modified once initially set up */
- { "immutable-streams", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(FALSE),
- G_STRUCT_OFFSET (TpsipConnParams, immutable_streams) },
- /* Local IP address to use, workaround purposes only */
- { "local-ip-address", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- 0, NULL, G_STRUCT_OFFSET (TpsipConnParams, local_ip_address) },
- /* Local port for SIP, workaround purposes only */
- { "local-port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT,
- 0, NULL, G_STRUCT_OFFSET (TpsipConnParams, local_port) },
- /* Extra-realm authentication */
- { "extra-auth-user", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- 0, NULL, G_STRUCT_OFFSET (TpsipConnParams, extra_auth_user) },
- { "extra-auth-password", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- TP_CONN_MGR_PARAM_FLAG_SECRET,
- NULL, G_STRUCT_OFFSET (TpsipConnParams, extra_auth_password) },
- { NULL, NULL, 0, 0, NULL, 0 }
-};
-
-const TpCMProtocolSpec tpsip_protocols[] = {
- { "sip", tpsip_params, alloc_params, free_params },
- { NULL, NULL }
-};
-
struct _TpsipConnectionManagerPrivate
{
su_root_t *sofia_root;
@@ -237,10 +79,24 @@ tpsip_connection_manager_init (TpsipConnectionManager *obj)
#endif
}
+static void
+tpsip_connection_manager_constructed (GObject *object)
+{
+ TpsipConnectionManager *self = TPSIP_CONNECTION_MANAGER (object);
+ TpBaseConnectionManager *base = (TpBaseConnectionManager *) self;
+ void (*constructed) (GObject *) =
+ ((GObjectClass *) tpsip_connection_manager_parent_class)->constructed;
+ TpBaseProtocol *protocol;
+
+ if (constructed != NULL)
+ constructed (object);
+
+ protocol = tpsip_protocol_new (self->priv->sofia_root);
+ tp_base_connection_manager_add_protocol (base, protocol);
+ g_object_unref (protocol);
+}
+
static void tpsip_connection_manager_finalize (GObject *object);
-static TpBaseConnection *tpsip_connection_manager_new_connection (
- TpBaseConnectionManager *base, const gchar *proto,
- TpIntSet *params_present, void *parsed_params, GError **error);
static void
tpsip_connection_manager_class_init (TpsipConnectionManagerClass *klass)
@@ -251,11 +107,10 @@ tpsip_connection_manager_class_init (TpsipConnectionManagerClass *klass)
g_type_class_add_private (klass, sizeof (TpsipConnectionManagerPrivate));
+ object_class->constructed = tpsip_connection_manager_constructed;
object_class->finalize = tpsip_connection_manager_finalize;
- base_class->new_connection = tpsip_connection_manager_new_connection;
base_class->cm_dbus_name = "sofiasip";
- base_class->protocol_params = tpsip_protocols;
}
void
@@ -279,248 +134,3 @@ tpsip_connection_manager_finalize (GObject *object)
G_OBJECT_CLASS (tpsip_connection_manager_parent_class)->finalize (object);
}
-
-static gchar *
-priv_compose_proxy_uri (const gchar *host,
- const gchar *transport,
- guint port)
-{
- const gchar *scheme = "sip";
-
- if (host == NULL)
- return NULL;
-
- /* Set scheme to SIPS if transport is TLS */
-
- if (transport != NULL && !g_ascii_strcasecmp (transport, "tls"))
- scheme = "sips";
-
- /* Format the resulting URI */
-
- if (port)
- return g_strdup_printf ("%s:%s:%u", scheme, host, port);
- else
- return g_strdup_printf ("%s:%s", scheme, host);
-}
-
-/**
- * Returns a default SIP proxy address based on the public
- * SIP address 'sip_address' and . For instance
- * "sip:first.surname@company.com" would result in "sip:company.com".
- * The SIP stack will further utilize DNS lookups to find the IP address
- * for the SIP server responsible for the domain "company.com".
- */
-static gchar *
-priv_compose_default_proxy_uri (const gchar *sip_address,
- const gchar *transport)
-{
- char *result = NULL;
- char *host;
- char *found;
-
- g_return_val_if_fail (sip_address != NULL, NULL);
-
- /* skip sip and sips prefixes, updating transport if necessary */
- found = strchr (sip_address, ':');
- if (found != NULL) {
- if (g_ascii_strncasecmp ("sip:", sip_address, 4) == 0)
- ;
- else if (g_ascii_strncasecmp ("sips:", sip_address, 5) == 0)
- {
- if (transport == NULL ||
- strcmp (transport, "auto") == 0)
- transport = "tls";
- }
- else
- {
- /* error, unknown URI prefix */
- return NULL;
- }
-
- sip_address = found + 1;
- }
-
- /* skip userinfo */
- found = strchr (sip_address, '@');
- if (found != NULL)
- sip_address = found + 1;
-
- /* copy rest of the string */
- host = g_strdup (sip_address);
-
- /* mark end (before uri-parameters defs or headers) */
- found = strchr (host, ';');
- if (found == NULL)
- found = strchr (host, '?');
- if (found != NULL)
- *found = '\0';
-
- result = priv_compose_proxy_uri (host, transport, 0);
-
- g_free (host);
-
- return result;
-}
-
-static TpsipConnectionKeepaliveMechanism
-priv_parse_keepalive (const gchar *str)
-{
- if (str == NULL || strcmp (str, "auto") == 0)
- return TPSIP_CONNECTION_KEEPALIVE_AUTO;
- if (strcmp (str, "register") == 0)
- return TPSIP_CONNECTION_KEEPALIVE_REGISTER;
- if (strcmp (str, "options") == 0)
- return TPSIP_CONNECTION_KEEPALIVE_OPTIONS;
- if (strcmp (str, "stun") == 0)
- return TPSIP_CONNECTION_KEEPALIVE_STUN;
- if (strcmp (str, "off") == 0)
- return TPSIP_CONNECTION_KEEPALIVE_NONE;
-
- WARNING ("unsupported keepalive-method value \"%s\", falling back to auto", str);
- return TPSIP_CONNECTION_KEEPALIVE_AUTO;
-}
-
-#define SET_PROPERTY_IF_PARAM_SET(prop, param, member) \
- if (tp_intset_is_member (params_present, param)) \
- { \
- g_object_set (connection, prop, member, NULL); \
- }
-
-#define NULLIFY_IF_EMPTY(param) \
- if ((param) != NULL && (param)[0] == '\0') \
- param = NULL;
-
-static gboolean
-check_not_empty_if_present (const gchar *name,
- const gchar *value,
- GError **error)
-{
- if (value != NULL && value[0] == '\0')
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "If supplied, '%s' account parameter may not be empty", name);
- return FALSE;
- }
- return TRUE;
-}
-
-static TpBaseConnection *
-tpsip_connection_manager_new_connection (TpBaseConnectionManager *base,
- const gchar *proto,
- TpIntSet *params_present,
- void *parsed_params,
- GError **error)
-{
- TpsipConnectionManager *self = TPSIP_CONNECTION_MANAGER (base);
- TpsipConnectionManagerPrivate *priv = TPSIP_CONNECTION_MANAGER_GET_PRIVATE (self);
- TpBaseConnection *connection = NULL;
- TpsipConnParams *params = (TpsipConnParams *)parsed_params;
- gchar *proxy = NULL;
- TpsipConnectionKeepaliveMechanism keepalive_mechanism;
-
- if (strcmp (proto, "sip")) {
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
- "This connection manager only implements protocol 'sip', not '%s'",
- proto);
- return NULL;
- }
-
- /* TpBaseConnectionManager code has already checked that required params
- * are present (but not that they are non-empty, if we're using >= 0.5.8)
- */
- g_assert (params->account);
-
- /* FIXME: validate account SIP URI properly, using appropriate RFCs */
- if (!check_not_empty_if_present ("account", params->account, error))
- return FALSE;
- NULLIFY_IF_EMPTY (params->auth_user);
- NULLIFY_IF_EMPTY (params->password);
- /* FIXME: validate registrar SIP URI properly, using appropriate RFCs */
- NULLIFY_IF_EMPTY (params->registrar);
- /* FIXME: validate proxy host properly */
- NULLIFY_IF_EMPTY (params->proxy_host);
- /* FIXME: check against the list (which presumably exists) of valid
- * transports */
- NULLIFY_IF_EMPTY (params->transport);
- /* FIXME: check against the list (which presumably exists) of valid
- * KA mechanisms */
- NULLIFY_IF_EMPTY (params->keepalive_mechanism);
- /* FIXME: validate STUN server properly */
- NULLIFY_IF_EMPTY (params->stun_server);
- /* FIXME: validate local IP address properly */
- NULLIFY_IF_EMPTY (params->local_ip_address);
- NULLIFY_IF_EMPTY (params->extra_auth_user);
- NULLIFY_IF_EMPTY (params->extra_auth_password);
-
- DEBUG("New SIP connection to %s", params->account);
-
- connection = (TpBaseConnection *)g_object_new(TPSIP_TYPE_CONNECTION,
- "protocol", "sip",
- "sofia-root", priv->sofia_root,
- "address", params->account,
- NULL);
-
- if (params->proxy_host == NULL) {
- proxy = priv_compose_default_proxy_uri (params->account,
- params->transport);
- DEBUG("set outbound proxy address to <%s>, based on <%s>", proxy, params->account);
- } else
- proxy = priv_compose_proxy_uri (params->proxy_host,
- params->transport,
- params->port);
-
- g_object_set (connection, "proxy", proxy, NULL);
- g_free (proxy);
-
- if (params->transport != NULL && strcmp (params->transport, "auto") != 0)
- g_object_set (connection, "transport", params->transport, NULL);
-
- SET_PROPERTY_IF_PARAM_SET ("auth-user", TPSIP_CONN_PARAM_AUTH_USER,
- params->auth_user);
-
- SET_PROPERTY_IF_PARAM_SET ("password", TPSIP_CONN_PARAM_PASSWORD,
- params->password);
-
- SET_PROPERTY_IF_PARAM_SET ("alias", TPSIP_CONN_PARAM_ALIAS,
- params->alias);
-
- SET_PROPERTY_IF_PARAM_SET ("registrar", TPSIP_CONN_PARAM_REGISTRAR,
- params->registrar);
-
- SET_PROPERTY_IF_PARAM_SET ("loose-routing", TPSIP_CONN_PARAM_LOOSE_ROUTING,
- params->loose_routing);
-
- SET_PROPERTY_IF_PARAM_SET ("discover-binding", TPSIP_CONN_PARAM_DISCOVER_BINDING,
- params->discover_binding);
-
- SET_PROPERTY_IF_PARAM_SET ("discover-stun", TPSIP_CONN_PARAM_DISCOVER_STUN,
- params->discover_stun);
-
- SET_PROPERTY_IF_PARAM_SET ("stun-server", TPSIP_CONN_PARAM_STUN_SERVER,
- params->stun_server);
-
- SET_PROPERTY_IF_PARAM_SET ("stun-port", TPSIP_CONN_PARAM_STUN_PORT,
- params->stun_port);
-
- SET_PROPERTY_IF_PARAM_SET ("immutable-streams", TPSIP_CONN_PARAM_IMMUTABLE_STREAMS,
- params->immutable_streams);
-
- SET_PROPERTY_IF_PARAM_SET ("keepalive-interval",
- TPSIP_CONN_PARAM_KEEPALIVE_INTERVAL, params->keepalive_interval);
-
- keepalive_mechanism = priv_parse_keepalive (params->keepalive_mechanism);
- g_object_set (connection, "keepalive-mechanism", keepalive_mechanism, NULL);
-
- SET_PROPERTY_IF_PARAM_SET ("local-ip-address", TPSIP_CONN_PARAM_LOCAL_IP_ADDRESS,
- params->local_ip_address);
-
- SET_PROPERTY_IF_PARAM_SET ("local-port", TPSIP_CONN_PARAM_LOCAL_PORT,
- params->local_port);
-
- SET_PROPERTY_IF_PARAM_SET ("extra-auth-user", TPSIP_CONN_PARAM_EXTRA_AUTH_USER,
- params->extra_auth_user);
- SET_PROPERTY_IF_PARAM_SET ("extra-auth-password", TPSIP_CONN_PARAM_EXTRA_AUTH_PASSWORD,
- params->extra_auth_password);
-
- return connection;
-}