GNetworkService: fall back when there is no valid SRV record

RFC 2782 says that if there is no SRV record for
_SERVICE._PROTOCOL.DOMAIN, you should fall back to trying just DOMAIN,
with the default port for SERVICE. Do that.

https://bugzilla.gnome.org/show_bug.cgi?id=629274
This commit is contained in:
Dan Winship
2010-09-15 10:05:03 -04:00
parent 19243c247d
commit e410131021

View File

@@ -361,6 +361,25 @@ g_network_service_set_scheme (GNetworkService *srv,
g_object_notify (G_OBJECT (srv), "scheme"); g_object_notify (G_OBJECT (srv), "scheme");
} }
static GList *
g_network_service_fallback_targets (GNetworkService *srv)
{
GSrvTarget *target;
struct servent *entry;
guint16 port;
entry = getservbyname (srv->priv->service, "tcp");
port = entry ? g_ntohs (entry->s_port) : 0;
#ifdef HAVE_ENDSERVENT
endservent ();
#endif
if (entry == NULL)
return NULL;
target = g_srv_target_new (srv->priv->domain, port, 0, 0);
return g_list_append (NULL, target);
}
#define G_TYPE_NETWORK_SERVICE_ADDRESS_ENUMERATOR (_g_network_service_address_enumerator_get_type ()) #define G_TYPE_NETWORK_SERVICE_ADDRESS_ENUMERATOR (_g_network_service_address_enumerator_get_type ())
#define G_NETWORK_SERVICE_ADDRESS_ENUMERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_NETWORK_SERVICE_ADDRESS_ENUMERATOR, GNetworkServiceAddressEnumerator)) #define G_NETWORK_SERVICE_ADDRESS_ENUMERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_NETWORK_SERVICE_ADDRESS_ENUMERATOR, GNetworkServiceAddressEnumerator))
@@ -401,14 +420,26 @@ g_network_service_address_enumerator_next (GSocketAddressEnumerator *enumerator
if (!srv_enum->srv->priv->targets) if (!srv_enum->srv->priv->targets)
{ {
GList *targets; GList *targets;
GError *my_error = NULL;
targets = g_resolver_lookup_service (srv_enum->resolver, targets = g_resolver_lookup_service (srv_enum->resolver,
srv_enum->srv->priv->service, srv_enum->srv->priv->service,
srv_enum->srv->priv->protocol, srv_enum->srv->priv->protocol,
srv_enum->srv->priv->domain, srv_enum->srv->priv->domain,
cancellable, error); cancellable, &my_error);
if (!targets && g_error_matches (my_error, G_RESOLVER_ERROR,
G_RESOLVER_ERROR_NOT_FOUND))
{
targets = g_network_service_fallback_targets (srv_enum->srv);
if (targets)
g_clear_error (&my_error);
}
if (!targets) if (!targets)
return NULL; {
g_propagate_error (error, my_error);
return NULL;
}
srv_enum->srv->priv->targets = targets; srv_enum->srv->priv->targets = targets;
srv_enum->t = srv_enum->srv->priv->targets; srv_enum->t = srv_enum->srv->priv->targets;
@@ -546,9 +577,18 @@ next_async_resolved_targets (GObject *source_object,
{ {
GNetworkServiceAddressEnumerator *srv_enum = user_data; GNetworkServiceAddressEnumerator *srv_enum = user_data;
GError *error = NULL; GError *error = NULL;
GList *targets;
srv_enum->srv->priv->targets = targets = g_resolver_lookup_service_finish (srv_enum->resolver,
g_resolver_lookup_service_finish (srv_enum->resolver, result, &error); result, &error);
if (!targets && g_error_matches (error, G_RESOLVER_ERROR,
G_RESOLVER_ERROR_NOT_FOUND))
{
targets = g_network_service_fallback_targets (srv_enum->srv);
if (targets)
g_clear_error (&error);
}
if (error) if (error)
{ {
@@ -562,7 +602,7 @@ next_async_resolved_targets (GObject *source_object,
} }
else else
{ {
srv_enum->t = srv_enum->srv->priv->targets; srv_enum->t = srv_enum->srv->priv->targets = targets;
next_async_have_targets (srv_enum); next_async_have_targets (srv_enum);
} }
} }