core: add support for internal device factories

This commit is contained in:
Dan Williams
2014-09-05 15:57:40 -05:00
parent 38b076de8f
commit 0bc1b5138a
4 changed files with 121 additions and 15 deletions

View File

@@ -27,6 +27,21 @@ enum {
};
static guint signals[LAST_SIGNAL] = { 0 };
static GSList *internal_types = NULL;
void
_nm_device_factory_internal_register_type (GType factory_type)
{
g_return_if_fail (g_slist_find (internal_types, GUINT_TO_POINTER (factory_type)) == NULL);
internal_types = g_slist_prepend (internal_types, GUINT_TO_POINTER (factory_type));
}
const GSList *
nm_device_factory_get_internal_factory_types (void)
{
return internal_types;
}
gboolean
nm_device_factory_emit_component_added (NMDeviceFactory *factory, GObject *component)
{

View File

@@ -168,5 +168,60 @@ NMDevice * nm_device_factory_create_virtual_device_for_connection (NMDeviceFacto
gboolean nm_device_factory_emit_component_added (NMDeviceFactory *factory,
GObject *component);
#endif /* __NETWORKMANAGER_DEVICE_FACTORY_H__ */
/**************************************************************************
* INTERNAL DEVICE FACTORY FUNCTIONS - devices provided by plugins should
* not use these functions.
**************************************************************************/
#define DEFINE_DEVICE_FACTORY_INTERNAL(upper, mixed, lower, dfi_code) \
DEFINE_DEVICE_FACTORY_INTERNAL_WITH_DEVTYPE(upper, mixed, lower, upper, dfi_code)
#define DEFINE_DEVICE_FACTORY_INTERNAL_WITH_DEVTYPE(upper, mixed, lower, devtype, dfi_code) \
typedef GObject NM##mixed##Factory; \
typedef GObjectClass NM##mixed##FactoryClass; \
\
static GType nm_##lower##_factory_get_type (void); \
static void device_factory_interface_init (NMDeviceFactory *factory_iface); \
\
G_DEFINE_TYPE_EXTENDED (NM##mixed##Factory, nm_##lower##_factory, G_TYPE_OBJECT, 0, \
G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init) \
_nm_device_factory_internal_register_type (g_define_type_id);) \
\
/* Use a module constructor to register the factory's GType at load \
* time, which then calls _nm_device_factory_internal_register_type() \
* to register the factory's GType with the Manager. \
*/ \
static void __attribute__((constructor)) \
register_device_factory_internal_##lower (void) \
{ \
g_type_init (); \
g_type_ensure (NM_TYPE_##upper##_FACTORY); \
} \
\
static NMDeviceType \
get_device_type (NMDeviceFactory *factory) \
{ \
return NM_DEVICE_TYPE_##devtype; \
} \
\
static void \
device_factory_interface_init (NMDeviceFactory *factory_iface) \
{ \
factory_iface->get_device_type = get_device_type; \
dfi_code \
} \
\
static void \
nm_##lower##_factory_init (NM##mixed##Factory *self) \
{ \
} \
\
static void \
nm_##lower##_factory_class_init (NM##mixed##FactoryClass *lower##_class) \
{ \
}
void _nm_device_factory_internal_register_type (GType factory_type);
const GSList *nm_device_factory_get_internal_factory_types (void);
#endif /* __NETWORKMANAGER_DEVICE_FACTORY_H__ */

View File

@@ -1968,6 +1968,7 @@ NEXT:
static gboolean
_register_device_factory (NMManager *self,
NMDeviceFactory *factory,
gboolean duplicate_check,
const char *path,
GError **error)
{
@@ -1975,15 +1976,17 @@ _register_device_factory (NMManager *self,
NMDeviceType ftype;
GSList *iter;
/* Make sure we don't double-register factories */
ftype = nm_device_factory_get_device_type (factory);
for (iter = priv->factories; iter; iter = iter->next) {
if (ftype == nm_device_factory_get_device_type (iter->data)) {
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_INTERNAL,
"multiple plugins for same type (using '%s' instead of '%s')",
(char *) g_object_get_data (G_OBJECT (iter->data), PLUGIN_PATH_TAG),
path);
return FALSE;
if (duplicate_check) {
/* Make sure we don't double-register factories */
ftype = nm_device_factory_get_device_type (factory);
for (iter = priv->factories; iter; iter = iter->next) {
if (ftype == nm_device_factory_get_device_type (iter->data)) {
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_INTERNAL,
"multiple plugins for same type (using '%s' instead of '%s')",
(char *) g_object_get_data (G_OBJECT (iter->data), PLUGIN_PATH_TAG),
path);
return FALSE;
}
}
}
@@ -2005,17 +2008,32 @@ _register_device_factory (NMManager *self,
static void
load_device_factories (NMManager *self)
{
char **path;
char **paths;
NMDeviceFactory *factory;
const GSList *iter;
GError *error = NULL;
char **path, **paths;
/* Register internal factories first */
for (iter = nm_device_factory_get_internal_factory_types (); iter; iter = iter->next) {
GType ftype = GPOINTER_TO_UINT (iter->data);
factory = (NMDeviceFactory *) g_object_new (ftype, NULL);
g_assert (factory);
if (_register_device_factory (self, factory, FALSE, "internal", &error)) {
nm_log_dbg (LOGD_HW, "Loaded device plugin: %s", g_type_name (ftype));
} else {
nm_log_warn (LOGD_HW, "Loading device plugin failed: %s", error->message);
g_object_unref (factory);
g_clear_error (&error);
}
}
paths = read_device_factory_paths ();
if (!paths)
return;
for (path = paths; *path; path++) {
GError *error = NULL;
GModule *plugin;
NMDeviceFactory *factory;
NMDeviceFactoryCreateFunc create_func;
const char *item;
@@ -2045,7 +2063,7 @@ load_device_factories (NMManager *self)
}
g_clear_error (&error);
if (_register_device_factory (self, factory, g_module_name (plugin), &error)) {
if (_register_device_factory (self, factory, TRUE, g_module_name (plugin), &error)) {
nm_log_info (LOGD_HW, "Loaded device plugin: %s", g_module_name (plugin));
g_module_make_resident (plugin);
} else {
@@ -2058,6 +2076,8 @@ load_device_factories (NMManager *self)
g_strfreev (paths);
}
/*******************************************************************/
static void
platform_link_added (NMManager *self,
int ifindex,

View File

@@ -95,3 +95,19 @@ TESTS = \
test-general-with-expect \
test-wired-defname
if ENABLE_TESTS
check-local:
@for t in ; do \
# Ensure the device subclass factory registration constructors exist \
# which could inadvertently break if src/Makefile.am gets changed \
if ! LC_ALL=C nm $(top_builddir)/src/NetworkManager | LC_ALL=C grep -q "register_device_factory_internal_$$t" ; then \
echo "Testing device factory symbols... FAILED" ; \
exit 1 ; \
fi \
done
@echo -n "Testing device factory symbols... PASSED"
endif