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

Reply via email to