Thanks a lot Dan, your explanations were very clear.
Thank to you I got a running example doing creation, connection,
disconnection and deletion of the settings. I attached the code I wrote.
It is not completely mature yet since it mixes c++ and C. But I intend
to put some orthodoxy in it later.
I have an other question, I have seen that the connection called "Test
of my" is still visible in the list of scanned networks displayed by the
network-manager-applet. I thought first that it was because the list was
not updated but it seems not to be the case. Worse: I am able to click
on it and it looks like it tries to activate it, however I think it does
not work.
Is this a problem related to the applet or did I miss to remove
something when managing the adhoc connection ?
Manuel
On 04/10/2014 05:52 PM, Dan Williams wrote:
On Thu, 2014-04-10 at 14:44 +0200, Manuel Yguel wrote:
I have successfully created and deleted adhoc networks from the glib API
thanks to Dan help. However my test program suffers from one problem:
the network connection configurations get stored in the network manager
memory and pollute the user interface. Thus I try to call
org.freedesktop.NetworkManager.Settings.Connection.Delete for a certain
NMConnection object without any success so far.
I can see in the D-bus (with qdbusviewer) the configuration for a single
network connection and I am able to call the Delete method on it
(because I can see it appears when the setting configuration is recorded).
However I do not know how to get the number (x) in the path that appears at
org/freedesktop/NetworkManager/Settings/x
in order to create a proxy for that "Settings.Connection object" and
call the Delete method on it later.
First I would like to know if there is a way to get the path of the
object storing the org.freedesktop.NetworkManager.Settings.Connection
from the glib API ?
When you add the connection to NetworkManager originally, NM will return
to you the object path that you can use to work with the Connection
object later. With the libnm-glib API, when you call:
gboolean nm_remote_settings_add_connection (NMRemoteSettings *settings,
NMConnection *connection,
NMRemoteSettingsAddConnectionFunc
callback,
gpointer user_data);
"callback" is called when the add is completed, and your callback has
the prototype of:
typedef void (*NMRemoteSettingsAddConnectionFunc) (NMRemoteSettings *settings,
NMRemoteConnection
*connection,
GError *error,
gpointer user_data);
The NMRemoteConnection object (a subclass of NMConnection) represents
the actual connection known by NM. You can throw away the NMConnection
that you handed to nm_remote_settings_add_connection(), it is unchanged
by the call. The NMRemoteConnection is the "live" object, which you can
keep around and use later with functions like:
void nm_remote_connection_delete (NMRemoteConnection *connection,
NMRemoteConnectionResultFunc callback,
gpointer user_data);
I was first thinking that it may be a NMSettingConnection object. I was
able to access it but I was only able to get the uuid or the human name
of the connection.
I also tried the nm_connection_get_path on the NMConnection object but I
get a NULL string.
I am quite stuck now and any help would be much appreciated.
I think the issue is that you might still be using the NMConnection that
you built up to send to NM with the add_connection() call. That object
isn't consumed by add_connection(), but serves as a template and can be
disposed after calling add_connection(). The NMRemoteConnection is what
you want to use.
I've committed some more documentation to libnm-glib's NMRemoteSettings
object which describes this and hopefully helps you out.
http://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=2200687b0f92d553dc79e54b672069b2b704203d
There are also some examples here, the ones you're interested in have
"libnm-glib" in the name:
http://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/examples/C/glib
Let us know if you have further questions!
Dan
#This CMakeLists.txt was automatically generated.
#You can add things but not change existing things.
#For instance don't change the variable names !
#One exception: you can change the name of the the target library.
cmake_minimum_required(VERSION 2.4)
if(COMMAND cmake_policy)
if( POLICY CMP0003 )
cmake_policy(SET CMP0003 NEW)
endif( POLICY CMP0003 )
if( POLICY CMP0015 )
cmake_policy(SET CMP0015 NEW)
endif( POLICY CMP0015 )
endif(COMMAND cmake_policy)
project( manage_adhoc_remote_connection_nm_glib )
if( NOT CMAKE_VERBOSE_MAKEFILE )
set( CMAKE_VERBOSE_MAKEFILE ON )
endif( NOT CMAKE_VERBOSE_MAKEFILE )
include( $ENV{CMAKE_COMPILE_VARIABLES} )
#C compiler
# TODO fix it for cmake 2.6 fucking version
#set( CMAKE_C_COMPILER ${CC_COMPILER} )
if( NOT FLAGS )
set( FLAGS "" )
endif( NOT FLAGS )
set( CMAKE_C_FLAGS_DEBUG "${CC_DEBUG_FLAGS} ${FLAGS}" )
set( CMAKE_C_FLAGS_RELEASE "${CC_OPTIMIZATION_FLAGS} ${FLAGS}" )
#C++ compiler
# TODO fix it for cmake 2.6 fucking version
#set( CMAKE_CXX_COMPILER ${CXX_COMPILER} )
set( CMAKE_CXX_FLAGS_DEBUG "${CXX_DEBUG_FLAGS} ${FLAGS}" )
set( CMAKE_CXX_FLAGS_RELEASE "${CXX_OPTIMIZATION_FLAGS} ${FLAGS}" )
#message( "flags: " ${FLAGS} )
if ( NOT CMAKE_BUILD_TYPE )
set ( CMAKE_BUILD_TYPE Debug )
endif ( NOT CMAKE_BUILD_TYPE )
#Find sources
file( GLOB manage_adhoc_remote_connection_nm_glib_files
${PROJECT_SOURCE_DIR}/[^~.]*.[cC] ${PROJECT_SOURCE_DIR}/[^~.]*.[cC]?? )
file( GLOB manage_adhoc_remote_connection_nm_glib_headers
${PROJECT_SOURCE_DIR}/[^~.]*.[thH] ${PROJECT_SOURCE_DIR}/[^~.]*.[thH]?? )
## Set CMAKE_MODULE_PATH which is a list
set(
CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
find_package( PkgConfig )
pkg_check_modules(WIFI_LINUX REQUIRED glib-2.0 dbus-glib-1 libnm-util
libnm-glib )
find_package( Boost 1.48.0 COMPONENTS system )
if ( Boost_SYSTEM_FOUND )
message( "\t\tBoost system found" )
else( Boost_SYSTEM_FOUND )
message( FATAL_ERROR "\t\tERROR: Boost system NOT found." )
endif( Boost_SYSTEM_FOUND )
#Program libraries
set( manage_adhoc_remote_connection_nm_glib_libs
${WIFI_LINUX_LIBRARIES} ${Boost_SYSTEM_LIBRARIES} )
#Program includes
include_directories( ${WIFI_LINUX_INCLUDE_DIRS} ${Boost_SYSTEM_INCLUDE_DIRS} )
#Program library paths
link_directories( ${WIFI_LINUX_LIBRARY_DIRS} )
#QT4
set( QT4_PROG_USED FALSE )
set( manage_adhoc_remote_connection_nm_glib_moc_files )
set( manage_adhoc_remote_connection_nm_glib_moc_headers )
if( QT4_PROG_USED )
qt4_find_headers( manage_adhoc_remote_connection_nm_glib_moc_headers
${manage_adhoc_remote_connection_nm_glib_headers} )
# the next line sets up include and link
#directories and defines some variables that we will use.
# you can modify the behavior by setting some variables, e.g.
#set(QT_USE_QTOPENGL TRUE)
# -> this will cause cmake to include and link against the OpenGL module
if( NOT QT4_USED )
find_package(Qt4 REQUIRED) # find and setup Qt4 for this project
include(${QT_USE_FILE})
include_directories( ${QT_QT_INCLUDE_DIR} )
# libraries
set( manage_adhoc_remote_connection_nm_glib_libs
${manage_adhoc_remote_connection_nm_glib_libs}
${QT_LIBRARIES} )
endif( NOT QT4_USED )
qt4_wrap_cpp( manage_adhoc_remote_connection_nm_glib_moc_files
${manage_adhoc_remote_connection_nm_glib_moc_headers} )
endif( QT4_PROG_USED )
#Program
add_executable( manage_adhoc_remote_connection_nm_glib
${manage_adhoc_remote_connection_nm_glib_files}
${manage_adhoc_remote_connection_nm_glib_moc_files} )
#Link
target_link_libraries( manage_adhoc_remote_connection_nm_glib
${manage_adhoc_remote_connection_nm_glib_libs} )
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
#INSTALL(TARGETS manage_adhoc_remote_connection_nm_glib DESTINATION ${THE_BINS}
)
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2011 Red Hat, Inc.
*/
/*
* The example shows how to call AddConnection() D-Bus method to add
* a connection to system settings service. It uses dbus-glib and libnm-util
* libraries.
*
* To compile the project use cmake
* $> mkdir buildTree; cd buildTree; cmake ..; make
*/
#include <stdlib.h>
#include <glib.h>
#include <dbus/dbus-glib.h>
#include <nm-connection.h>
#include <nm-setting-connection.h>
#include <nm-setting-wireless.h>
#include <nm-setting-ip4-config.h>
#include <NetworkManager.h>
#include <nm-utils.h>
#include <nm-client.h>
#include <nm-device.h>
#include <nm-device-wifi.h>
#include <nm-access-point.h>
#include <boost/asio.hpp>
#include <iostream>
#include <string>
#include <glib.h>
#include <nm-remote-settings.h>
#include <nm-connection.h>
#include <nm-setting-connection.h>
#include <nm-setting-wired.h>
#include <nm-setting-ip4-config.h>
#include <nm-utils.h>
struct ConnectionHelpers
{
GMainLoop *loop;
NMDevice *wifi_device;
NMRemoteConnection *remote;
};
static
void remove_cb( NMRemoteConnection * /*connection*/,
GError * /*error*/,
gpointer user_data )
{
g_print( "\tSettings removed.\n");
ConnectionHelpers *helpers = (ConnectionHelpers *)user_data;
/* Tell the mainloop we're done and we can quit now */
g_main_loop_quit (helpers->loop);
}
static
void disconnect_cb( NMDevice * /*device*/, GError * /*error*/, gpointer user_data)
{
g_print( "\tConnection disconnected.\n");
ConnectionHelpers *helpers = (ConnectionHelpers *)user_data;
NMRemoteConnection *remote = helpers->remote;
nm_remote_connection_delete( remote, remove_cb, user_data );
}
static
void added_cb (NMRemoteSettings * /*settings*/,
NMRemoteConnection *remote,
GError *error,
gpointer user_data)
{
g_print( "\tConnection created!\n" );
ConnectionHelpers *helpers = (ConnectionHelpers *)user_data;
GMainLoop *loop = helpers->loop;//(GMainLoop *)user_data;
helpers->remote = remote;
/* NM responded to our request; either handle the resulting error or
* print out the object path of the connection we just added.
*/
if (error) {
g_print ("Error adding connection: %s", error->message); }
else {
g_print ("Added: %s\n", nm_connection_get_path (NM_CONNECTION (remote))); }
DBusGConnection *bus;
DBusGProxy *proxy2;
/* Get system bus */
bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
/* Create a D-Bus proxy to get the object properties from the NM Manager
* object. NM_DBUS_* defines are from NetworkManager.h.
*/
proxy2 = dbus_g_proxy_new_for_name (bus,
NM_DBUS_SERVICE,
NM_DBUS_PATH,
NM_DBUS_INTERFACE);
/* Get NMClient object */
NMClient *client;
client = nm_client_new ();
if (!client)
{
dbus_g_connection_unref (bus);
g_message ("Error: Could not create NMClient.");
exit(-1);
}
/* Get all devices managed by NetworkManager */
const GPtrArray *devices = nm_client_get_devices (client);
NMDevice *wifi_device=NULL;
/* Go through the array and process Wi-Fi devices */
for (unsigned int i = 0; devices && (i < devices->len); i++)
{
NMDevice *device = (NMDevice *)g_ptr_array_index (devices, i);
if (NM_IS_DEVICE_WIFI (device))
{
wifi_device = device;
break;
}
}
helpers->wifi_device = wifi_device;
error = NULL;
GByteArray *new_active_path=NULL;
/** Needs to know how to use dbus */
if(!dbus_g_proxy_call ( proxy2, "ActivateConnection", &error,
DBUS_TYPE_G_OBJECT_PATH, nm_connection_get_path (NM_CONNECTION (remote)),
DBUS_TYPE_G_OBJECT_PATH, nm_object_get_path((NMObject *)wifi_device),
DBUS_TYPE_G_OBJECT_PATH, "/",
G_TYPE_INVALID,
DBUS_TYPE_G_OBJECT_PATH, &new_active_path,
G_TYPE_INVALID))
{
g_print ("Error activating connection: %s %s",
dbus_g_error_get_name (error),
error->message);
g_clear_error (&error);
}
else{
g_print( "\tConnection activated!\n" ); }
g_free (new_active_path);
/* Tell the mainloop we're done and we can quit now */
g_main_loop_quit (loop);
}
static gboolean
add_connection (NMRemoteSettings *settings, ConnectionHelpers *helpers, const char *con_name)
{
NMConnection *connection;
NMSettingConnection *s_con;
NMSettingWireless *s_wireless;
NMSettingIP4Config *s_ip4;
char *uuid;
GByteArray *ssid;
const unsigned char ssid_data[] = { 'T', 'e', 's', 't', ' ', 'o', 'f', ' ', 'm', 'y' };//Test of my own wifi network
gboolean success;
/* Create a new connection object */
connection = nm_connection_new ();
/* Build up the 'connection' Setting */
{
s_con = (NMSettingConnection *) nm_setting_connection_new ();
uuid = nm_utils_uuid_generate ();
g_object_set (G_OBJECT (s_con),
NM_SETTING_CONNECTION_UUID, uuid,
NM_SETTING_CONNECTION_ID, con_name,
NM_SETTING_CONNECTION_TYPE, "802-11-wireless",
NULL);
g_free (uuid);
nm_connection_add_setting (connection, NM_SETTING (s_con));
/* Build up the 'wireless' Setting */
s_wireless = (NMSettingWireless *) nm_setting_wireless_new ();
nm_connection_add_setting (connection, NM_SETTING (s_wireless));
ssid = g_byte_array_sized_new (sizeof (ssid_data));
g_byte_array_append (ssid, ssid_data, sizeof (ssid_data));
g_object_set(s_wireless, NM_SETTING_WIRELESS_SSID, ssid, NULL);
g_object_set(s_wireless, NM_SETTING_WIRELESS_MODE, "adhoc", NULL);
g_byte_array_free (ssid, TRUE);
/* Build up the 'ipv4' Setting */
s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
g_object_set (G_OBJECT (s_ip4),
NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
NULL);
nm_connection_add_setting (connection, NM_SETTING (s_ip4));
}
/* Ask the settings service to add the new connection; we'll quit the
* mainloop and exit when the callback is called.
*/
success = nm_remote_settings_add_connection (settings, connection, added_cb, helpers);
if (!success) {
g_print ("Error adding connection\n"); }
g_object_unref (connection);
return success;
}
int main (int /*argc*/, char * /*argv*/[])
{
DBusGConnection *bus;
NMRemoteSettings *settings;
GMainLoop *loop;
ConnectionHelpers *helpers;
g_print("Test of adhoc network handling through network-manager:\n"
"create, activate, disconnect, delete.\n");
/* Initialize GType system */
g_type_init ();
loop = g_main_loop_new (NULL, FALSE);
helpers = new ConnectionHelpers;
helpers->loop = loop;
/* Get system bus */
bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
/* Create our proxy for NetworkManager's settings service */
settings = nm_remote_settings_new (bus);
/* Ask the settings service to add the new connection */
if (add_connection (settings, helpers, "__Test wireless adhoc network creation__"))
{
/* Wait for the connection to be added */
g_main_loop_run (loop);
}
else {
g_print ("Error adding connection to NetworkManager\n"); }
{//Waiting
using namespace boost::asio;
io_service io_s;
deadline_timer timer(io_s);
// Set an expiry time relative to now.
timer.expires_from_now(boost::posix_time::seconds(3));
// Wait for the timer to expire.
timer.wait();
}
/* Disconnect the device then remove the settings in the callback function */
nm_device_disconnect( helpers->wifi_device, disconnect_cb, helpers );
g_main_loop_run (loop);
/* Clean up */
delete helpers;
g_object_unref (settings);
dbus_g_connection_unref (bus);
return 0;
}
_______________________________________________
networkmanager-list mailing list
networkmanager-list@gnome.org
https://mail.gnome.org/mailman/listinfo/networkmanager-list