mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 07:26:15 +01:00
GInetSocketAddress: add IPv6 flowinfo and scope_id fields
struct sin6_addr has two additional fields that struct sin_addr doesn't. Add support for those to GInetSocketAddress, and make sure they don't get lost when converting between glib and native types. https://bugzilla.gnome.org/show_bug.cgi?id=635554
This commit is contained in:
parent
c71fc7477e
commit
bf7408c30b
@ -1594,6 +1594,8 @@ GInetSocketAddress
|
|||||||
g_inet_socket_address_new
|
g_inet_socket_address_new
|
||||||
g_inet_socket_address_get_address
|
g_inet_socket_address_get_address
|
||||||
g_inet_socket_address_get_port
|
g_inet_socket_address_get_port
|
||||||
|
g_inet_socket_address_get_flowinfo
|
||||||
|
g_inet_socket_address_get_scope_id
|
||||||
<SUBSECTION Standard>
|
<SUBSECTION Standard>
|
||||||
GInetSocketAddressClass
|
GInetSocketAddressClass
|
||||||
GInetSocketAddressPrivate
|
GInetSocketAddressPrivate
|
||||||
|
@ -51,13 +51,17 @@ G_DEFINE_TYPE (GInetSocketAddress, g_inet_socket_address, G_TYPE_SOCKET_ADDRESS)
|
|||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_ADDRESS,
|
PROP_ADDRESS,
|
||||||
PROP_PORT
|
PROP_PORT,
|
||||||
|
PROP_FLOWINFO,
|
||||||
|
PROP_SCOPE_ID
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GInetSocketAddressPrivate
|
struct _GInetSocketAddressPrivate
|
||||||
{
|
{
|
||||||
GInetAddress *address;
|
GInetAddress *address;
|
||||||
guint16 port;
|
guint16 port;
|
||||||
|
guint32 flowinfo;
|
||||||
|
guint32 scope_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -98,6 +102,16 @@ g_inet_socket_address_get_property (GObject *object,
|
|||||||
g_value_set_uint (value, address->priv->port);
|
g_value_set_uint (value, address->priv->port);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_FLOWINFO:
|
||||||
|
g_return_if_fail (g_inet_address_get_family (address->priv->address) == G_SOCKET_FAMILY_IPV6);
|
||||||
|
g_value_set_uint (value, address->priv->flowinfo);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_SCOPE_ID:
|
||||||
|
g_return_if_fail (g_inet_address_get_family (address->priv->address) == G_SOCKET_FAMILY_IPV6);
|
||||||
|
g_value_set_uint (value, address->priv->scope_id);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
}
|
}
|
||||||
@ -121,6 +135,17 @@ g_inet_socket_address_set_property (GObject *object,
|
|||||||
address->priv->port = (guint16) g_value_get_uint (value);
|
address->priv->port = (guint16) g_value_get_uint (value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_FLOWINFO:
|
||||||
|
/* We can't test that address->priv->address is IPv6 here,
|
||||||
|
* since this property might get set before PROP_ADDRESS.
|
||||||
|
*/
|
||||||
|
address->priv->flowinfo = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_SCOPE_ID:
|
||||||
|
address->priv->scope_id = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
}
|
}
|
||||||
@ -202,6 +227,8 @@ g_inet_socket_address_to_native (GSocketAddress *address,
|
|||||||
memset (sock, 0, sizeof (*sock));
|
memset (sock, 0, sizeof (*sock));
|
||||||
sock->sin6_family = AF_INET6;
|
sock->sin6_family = AF_INET6;
|
||||||
sock->sin6_port = g_htons (addr->priv->port);
|
sock->sin6_port = g_htons (addr->priv->port);
|
||||||
|
sock->sin6_flowinfo = g_htonl (addr->priv->flowinfo);
|
||||||
|
sock->sin6_scope_id = g_htonl (addr->priv->scope_id);
|
||||||
memcpy (&(sock->sin6_addr.s6_addr), g_inet_address_to_bytes (addr->priv->address), sizeof (sock->sin6_addr));
|
memcpy (&(sock->sin6_addr.s6_addr), g_inet_address_to_bytes (addr->priv->address), sizeof (sock->sin6_addr));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -249,6 +276,42 @@ g_inet_socket_address_class_init (GInetSocketAddressClass *klass)
|
|||||||
G_PARAM_CONSTRUCT_ONLY |
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
G_PARAM_READWRITE |
|
G_PARAM_READWRITE |
|
||||||
G_PARAM_STATIC_STRINGS));
|
G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GInetSocketAddress:flowinfo:
|
||||||
|
*
|
||||||
|
* The <literal>sin6_flowinfo</literal> field, for IPv6 addresses.
|
||||||
|
*
|
||||||
|
* Since: 2.32
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_FLOWINFO,
|
||||||
|
g_param_spec_uint ("flowinfo",
|
||||||
|
P_("Flow info"),
|
||||||
|
P_("IPv6 flow info"),
|
||||||
|
0,
|
||||||
|
G_MAXUINT32,
|
||||||
|
0,
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GInetSocketAddress:scope_id:
|
||||||
|
*
|
||||||
|
* The <literal>sin6_scope_id</literal> field, for IPv6 addresses.
|
||||||
|
*
|
||||||
|
* Since: 2.32
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_SCOPE_ID,
|
||||||
|
g_param_spec_uint ("scope-id",
|
||||||
|
P_("Scope ID"),
|
||||||
|
P_("IPv6 scope ID"),
|
||||||
|
0,
|
||||||
|
G_MAXUINT32,
|
||||||
|
0,
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -257,9 +320,6 @@ g_inet_socket_address_init (GInetSocketAddress *address)
|
|||||||
address->priv = G_TYPE_INSTANCE_GET_PRIVATE (address,
|
address->priv = G_TYPE_INSTANCE_GET_PRIVATE (address,
|
||||||
G_TYPE_INET_SOCKET_ADDRESS,
|
G_TYPE_INET_SOCKET_ADDRESS,
|
||||||
GInetSocketAddressPrivate);
|
GInetSocketAddressPrivate);
|
||||||
|
|
||||||
address->priv->address = NULL;
|
|
||||||
address->priv->port = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -319,3 +379,44 @@ g_inet_socket_address_get_port (GInetSocketAddress *address)
|
|||||||
|
|
||||||
return address->priv->port;
|
return address->priv->port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_inet_socket_address_get_flowinfo:
|
||||||
|
* @address: a %G_SOCKET_FAMILY_IPV6 #GInetSocketAddress
|
||||||
|
*
|
||||||
|
* Gets the <literal>sin6_flowinfo</literal> field from @address,
|
||||||
|
* which must be an IPv6 address.
|
||||||
|
*
|
||||||
|
* Return value: the flowinfo field
|
||||||
|
*
|
||||||
|
* Since: 2.32
|
||||||
|
*/
|
||||||
|
guint32
|
||||||
|
g_inet_socket_address_get_flowinfo (GInetSocketAddress *address)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0);
|
||||||
|
g_return_val_if_fail (g_inet_address_get_family (address->priv->address) == G_SOCKET_FAMILY_IPV6, 0);
|
||||||
|
|
||||||
|
return address->priv->flowinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_inet_address_get_scope_id:
|
||||||
|
* @address: a %G_SOCKET_FAMILY_IPV6 #GInetAddress
|
||||||
|
*
|
||||||
|
* Gets the <literal>sin6_scope_id</literal> field from @address,
|
||||||
|
* which must be an IPv6 address.
|
||||||
|
*
|
||||||
|
* Return value: the scope id field
|
||||||
|
*
|
||||||
|
* Since: 2.32
|
||||||
|
*/
|
||||||
|
guint32
|
||||||
|
g_inet_socket_address_get_scope_id (GInetSocketAddress *address)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), 0);
|
||||||
|
g_return_val_if_fail (g_inet_address_get_family (address->priv->address) == G_SOCKET_FAMILY_IPV6, 0);
|
||||||
|
|
||||||
|
return address->priv->scope_id;
|
||||||
|
}
|
||||||
|
@ -55,14 +55,16 @@ struct _GInetSocketAddressClass
|
|||||||
GSocketAddressClass parent_class;
|
GSocketAddressClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType g_inet_socket_address_get_type (void) G_GNUC_CONST;
|
GType g_inet_socket_address_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
GSocketAddress *g_inet_socket_address_new (GInetAddress *address,
|
GSocketAddress *g_inet_socket_address_new (GInetAddress *address,
|
||||||
guint16 port);
|
guint16 port);
|
||||||
|
|
||||||
GInetAddress * g_inet_socket_address_get_address (GInetSocketAddress *address);
|
GInetAddress * g_inet_socket_address_get_address (GInetSocketAddress *address);
|
||||||
|
guint16 g_inet_socket_address_get_port (GInetSocketAddress *address);
|
||||||
|
|
||||||
guint16 g_inet_socket_address_get_port (GInetSocketAddress *address);
|
guint32 g_inet_socket_address_get_flowinfo (GInetSocketAddress *address);
|
||||||
|
guint32 g_inet_socket_address_get_scope_id (GInetSocketAddress *address);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -842,7 +842,9 @@ g_inet_address_mask_get_type
|
|||||||
g_inet_address_mask_matches
|
g_inet_address_mask_matches
|
||||||
g_inet_address_mask_equal
|
g_inet_address_mask_equal
|
||||||
g_inet_socket_address_get_address
|
g_inet_socket_address_get_address
|
||||||
|
g_inet_socket_address_get_flowinfo
|
||||||
g_inet_socket_address_get_port
|
g_inet_socket_address_get_port
|
||||||
|
g_inet_socket_address_get_scope_id
|
||||||
g_inet_socket_address_get_type
|
g_inet_socket_address_get_type
|
||||||
g_inet_socket_address_new
|
g_inet_socket_address_new
|
||||||
#ifdef G_OS_UNIX
|
#ifdef G_OS_UNIX
|
||||||
|
@ -256,7 +256,12 @@ g_socket_address_new_from_native (gpointer native,
|
|||||||
iaddr = g_inet_address_new_from_bytes ((guint8 *) &(addr->sin6_addr), AF_INET6);
|
iaddr = g_inet_address_new_from_bytes ((guint8 *) &(addr->sin6_addr), AF_INET6);
|
||||||
}
|
}
|
||||||
|
|
||||||
sockaddr = g_inet_socket_address_new (iaddr, g_ntohs (addr->sin6_port));
|
sockaddr = g_object_new (G_TYPE_INET_SOCKET_ADDRESS,
|
||||||
|
"address", iaddr,
|
||||||
|
"port", g_ntohs (addr->sin6_port),
|
||||||
|
"flowinfo", g_ntohl (addr->sin6_flowinfo),
|
||||||
|
"scope_id", g_ntohl (addr->sin6_scope_id),
|
||||||
|
NULL);
|
||||||
g_object_unref (iaddr);
|
g_object_unref (iaddr);
|
||||||
return sockaddr;
|
return sockaddr;
|
||||||
}
|
}
|
||||||
|
@ -499,6 +499,45 @@ test_ipv6_v4mapped (void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_sockaddr (void)
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 sin6, gsin6;
|
||||||
|
GSocketAddress *saddr;
|
||||||
|
GInetSocketAddress *isaddr;
|
||||||
|
GInetAddress *iaddr;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
memset (&sin6, 0, sizeof (sin6));
|
||||||
|
sin6.sin6_family = AF_INET6;
|
||||||
|
sin6.sin6_addr = in6addr_loopback;
|
||||||
|
sin6.sin6_port = g_htons (42);
|
||||||
|
sin6.sin6_scope_id = g_htonl (17);
|
||||||
|
sin6.sin6_flowinfo = g_htonl (1729);
|
||||||
|
|
||||||
|
saddr = g_socket_address_new_from_native (&sin6, sizeof (sin6));
|
||||||
|
g_assert (G_IS_INET_SOCKET_ADDRESS (saddr));
|
||||||
|
|
||||||
|
isaddr = G_INET_SOCKET_ADDRESS (saddr);
|
||||||
|
iaddr = g_inet_socket_address_get_address (isaddr);
|
||||||
|
g_assert_cmpint (g_inet_address_get_family (iaddr), ==, G_SOCKET_FAMILY_IPV6);
|
||||||
|
g_assert (g_inet_address_get_is_loopback (iaddr));
|
||||||
|
|
||||||
|
g_assert_cmpint (g_inet_socket_address_get_port (isaddr), ==, 42);
|
||||||
|
g_assert_cmpint (g_inet_socket_address_get_scope_id (isaddr), ==, 17);
|
||||||
|
g_assert_cmpint (g_inet_socket_address_get_flowinfo (isaddr), ==, 1729);
|
||||||
|
|
||||||
|
g_socket_address_to_native (saddr, &gsin6, sizeof (gsin6), &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
g_assert (memcmp (&sin6.sin6_addr, &gsin6.sin6_addr, sizeof (struct in6_addr)) == 0);
|
||||||
|
g_assert_cmpint (sin6.sin6_port, ==, gsin6.sin6_port);
|
||||||
|
g_assert_cmpint (sin6.sin6_scope_id, ==, gsin6.sin6_scope_id);
|
||||||
|
g_assert_cmpint (sin6.sin6_flowinfo, ==, gsin6.sin6_flowinfo);
|
||||||
|
|
||||||
|
g_object_unref (saddr);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef G_OS_UNIX
|
#ifdef G_OS_UNIX
|
||||||
static void
|
static void
|
||||||
test_unix_from_fd (void)
|
test_unix_from_fd (void)
|
||||||
@ -654,6 +693,7 @@ main (int argc,
|
|||||||
#if defined (IPPROTO_IPV6) && defined (IPV6_V6ONLY)
|
#if defined (IPPROTO_IPV6) && defined (IPV6_V6ONLY)
|
||||||
g_test_add_func ("/socket/ipv6_v4mapped", test_ipv6_v4mapped);
|
g_test_add_func ("/socket/ipv6_v4mapped", test_ipv6_v4mapped);
|
||||||
#endif
|
#endif
|
||||||
|
g_test_add_func ("/socket/address", test_sockaddr);
|
||||||
#ifdef G_OS_UNIX
|
#ifdef G_OS_UNIX
|
||||||
g_test_add_func ("/socket/unix-from-fd", test_unix_from_fd);
|
g_test_add_func ("/socket/unix-from-fd", test_unix_from_fd);
|
||||||
g_test_add_func ("/socket/unix-connection", test_unix_connection);
|
g_test_add_func ("/socket/unix-connection", test_unix_connection);
|
||||||
|
Loading…
Reference in New Issue
Block a user