Blame docs/libnm/html/usage.html

Packit 5756e2
Packit 5756e2
<html>
Packit 5756e2
<head>
Packit 5756e2
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
Packit 5756e2
<title>Using libnm: libnm Reference Manual</title>
Packit 5756e2
<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
Packit 5756e2
<link rel="home" href="index.html" title="libnm Reference Manual">
Packit 5756e2
<link rel="up" href="ref-overview.html" title="Overview">
Packit 5756e2
<link rel="prev" href="ref-overview.html" title="Overview">
Packit 5756e2
<link rel="next" href="ch02.html" title="Client Object API Reference">
Packit Service 018b0a
<meta name="generator" content="GTK-Doc V1.33.0 (XML mode)">
Packit 5756e2
<link rel="stylesheet" href="style.css" type="text/css">
Packit 5756e2
</head>
Packit 5756e2
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
Packit 5756e2
Packit 5756e2
Packit 5756e2
Home
Packit 5756e2
Up
Packit 5756e2
Prev
Packit 5756e2
Next
Packit 5756e2
Packit 5756e2
Packit 5756e2

Packit 5756e2
Using libnm
Packit 5756e2
Packit 5756e2

Packit 5756e2
When to use libnm
Packit 5756e2

Packit 5756e2
          libnm is fairly simple to use from C. It's based on glib and GObject.
Packit 5756e2
          If your project uses these already you'll find integration libnm with your
Packit 5756e2
          project rather convenient. In fact, the nmcli tool shipped
Packit 5756e2
          with NetworkManager is based on libnm.
Packit 5756e2
        

Packit 5756e2

Packit 5756e2
          libnm should be also the way to go if your project does something non-trivial
Packit 5756e2
          with NetworkManager, such as manipulating the connection profiles.
Packit 5756e2
          That is, if you're writing a specialized networking control tool or a desktop
Packit 5756e2
          environment, libnm is probably the right choice. The popular desktop
Packit 5756e2
          environments in fact all use libnm directly or with nm-applet and
Packit 5756e2
          nm-connection-editor that are all based on libnm.
Packit 5756e2
        

Packit 5756e2

Packit 5756e2
          An alternative to use of libnm is the use of the
Packit 5756e2
          D-Bus API
Packit 5756e2
          directly.  This gives you larger flexibility and reduces the overhead of linking
Packit 5756e2
          with the libnm library. This makes sense if your task is simple and you have a good
Packit 5756e2
          D-Bus library at your disposal. Activating a particular connection profile
Packit 5756e2
          from a Python script is a good example of a task that is perfectly simple
Packit 5756e2
          without using libnm.
Packit 5756e2
        

Packit 5756e2
Packit 5756e2
Packit 5756e2

Packit 5756e2
How to use libnm
Packit 5756e2

Packit 5756e2
          You can use the libnm's C API directly. To do so, all libnm programs need to
Packit 5756e2
          include NetworkManager.h that provides necessary definitions.
Packit 5756e2
          The rest of the API is documented in the reference manual.
Packit 5756e2
        

Packit 5756e2
Packit 5756e2
  
Packit 5756e2
    
Packit 5756e2
      
Packit 5756e2
        
1
Packit 5756e2
2
Packit 5756e2
3
Packit 5756e2
4
Packit 5756e2
5
Packit 5756e2
6
Packit 5756e2
7
Packit 5756e2
8
Packit 5756e2
9
Packit 5756e2
10
Packit 5756e2
11
Packit 5756e2
12
Packit 5756e2
        
#include <glib.h>
Packit 5756e2
#include <NetworkManager.h>
Packit 5756e2
Packit 5756e2
int
Packit 5756e2
main (int argc, char *argv[])
Packit 5756e2
{
Packit 5756e2
	NMClient *client;
Packit 5756e2
Packit 5756e2
	client = nm_client_new (NULL, NULL);
Packit 5756e2
	if (client)
Packit 5756e2
		g_print ("NetworkManager version: %s\n", nm_client_get_version (client));
Packit 5756e2
}
Packit 5756e2
      
Packit 5756e2
    
Packit 5756e2
  
Packit 5756e2
Packit 5756e2
Packit 5756e2

Packit 5756e2
          Use pkg-config for libnm to discover the necessary
Packit 5756e2
          compiler flags.
Packit 5756e2
        

Packit 5756e2
$ cc $(pkg-config --libs --cflags libnm) -o hello-nm hello-nm.c
Packit 5756e2
  $ ./hello-nm
Packit Service 018b0a
  NetworkManager version: 1.29.10
Packit 5756e2
Packit 5756e2
  $ 
Packit 5756e2

Packit 5756e2
          Utilize the PKG_CHECK_MODULES macro to integrate with an
Packit 5756e2
          autoconf-based build system. It's also recommended to use
Packit 5756e2
          NM_VERSION_MIN_REQUIRED and NM_VERSION_MAX_ALLOWED
Packit 5756e2
          macros to tell libnm headers which API version does your application need to work with.
Packit 5756e2
          If you use them, the compiler will warn you when you use functionality that is not
Packit 5756e2
          available in the versions you specified.
Packit 5756e2
        

Packit 5756e2
Packit 5756e2
  
Packit 5756e2
    
Packit 5756e2
      
Packit 5756e2
        
1
Packit 5756e2
2
Packit 5756e2
3
Packit 5756e2
        
PKG_CHECK_MODULES(LIBNM, libnm >= 1.8)
Packit 5756e2
LIBNM_CFLAGS="$LIBNM_CFLAGS -DNM_VERSION_MIN_REQUIRED=NM_VERSION_1_8"
Packit 5756e2
LIBNM_CFLAGS="$LIBNM_CFLAGS -DNM_VERSION_MAX_ALLOWED=NM_VERSION_1_8"
Packit 5756e2
      
Packit 5756e2
    
Packit 5756e2
  
Packit 5756e2
Packit 5756e2
Packit 5756e2

Packit 5756e2
          You can use libnm from other languages than C with the use of GObject introspection.
Packit 5756e2
          This includes Perl, Python, Javascript, Lua, Ruby and more. The example below shows what the
Packit 5756e2
          typical libnm use in Python would look like.
Packit 5756e2
        

Packit 5756e2
Packit 5756e2
  
Packit 5756e2
    
Packit 5756e2
      
Packit 5756e2
        
1
Packit 5756e2
2
Packit 5756e2
3
Packit 5756e2
4
Packit 5756e2
5
Packit 5756e2
6
Packit 5756e2
        
import gi
Packit 5756e2
gi.require_version('NM', '1.0')
Packit 5756e2
from gi.repository import NM
Packit 5756e2
Packit 5756e2
client = NM.Client.new(None)
Packit 5756e2
print ("NetworkManager version " + client.get_version())
Packit 5756e2
      
Packit 5756e2
    
Packit 5756e2
  
Packit 5756e2
Packit 5756e2
Packit 5756e2

Packit 5756e2
          There's NM-1.0 Python API Reference
Packit 5756e2
          maintained a third party that is generated from the introspection metadata.
Packit 5756e2
        

Packit 5756e2

Packit 5756e2
          In general, the C API documentation applies to the use GObject introspection
Packit 5756e2
          from other languages, with the calling convention respecting the language's
Packit 5756e2
          customs. Consult the source tree for
Packit 5756e2
          some examples.
Packit 5756e2
        

Packit 5756e2
Packit 5756e2
Packit 5756e2

Packit 5756e2
Synchronous API in libnm
Packit 5756e2

Packit 5756e2
          Libnm contains some synchronous API. This API basically makes a blocking
Packit 5756e2
          D-Bus call (g_dbus_connection_call_sync()) and is now deprecated.
Packit 5756e2
        

Packit 5756e2

Packit 5756e2
          Note that D-Bus is fundamentally asynchronous. Doing blocking calls
Packit 5756e2
          on top of D-Bus is odd, especially for libnm's NMClient. That is because
Packit 5756e2
          NMClient essentially is a client-side cache of the objects of the D-Bus
Packit 5756e2
          interface. This cache should be filled exclusively by (asynchronous) D-Bus
Packit 5756e2
          events. So, making a blocking D-Bus call means to wait for a response and
Packit 5756e2
          return it, while queuing everything that happens in between. Basically,
Packit 5756e2
          there are three options how a synchronous API on NMClient could behave:
Packit 5756e2
          

Packit 5756e2
    Packit 5756e2
  1. Packit 5756e2
                    The call basically calls g_dbus_connection_call_sync(). This means
    Packit 5756e2
                    that libnm sends a D-Bus request via GDBusConnection, and blockingly
    Packit 5756e2
                    waits for the response. All D-Bus messages that get received in the
    Packit 5756e2
                    meantime are queued in the GMainContext that belongs to NMClient.
    Packit 5756e2
                    That means, none of these D-Bus events are processed until we
    Packit 5756e2
                    iterate the GMainContext after the call returns. The effect is,
    Packit 5756e2
                    that NMClient (and all cached objects in there) are unaffected by
    Packit 5756e2
                    the D-Bus request.
    Packit 5756e2
                    Most of the synchronous API calls in libnm are of this kind.
    Packit 5756e2
                    The problem is that the strict ordering of D-Bus events gets
    Packit 5756e2
                    violated.
    Packit 5756e2
                    For some API this is not an immediate problem. Take for example
    Packit 5756e2
                    nm_device_wifi_request_scan(). The call merely blockingly tells
    Packit 5756e2
                    NetworkManager to start scanning, but since NetworkManager's D-Bus
    Packit 5756e2
                    API does not directly expose any state that tells whether we are
    Packit 5756e2
                    currently scanning, this out of order processing of the D-Bus
    Packit 5756e2
                    request is a small issue.
    Packit 5756e2
                    The problem is more obvious for nm_client_networking_set_enabled().
    Packit 5756e2
                    After calling it, NM_CLIENT_NETWORKING_ENABLED is still unaffected
    Packit 5756e2
                    and unchanged, because the PropertiesChanged signal from D-Bus
    Packit 5756e2
                    is not yet processed.
    Packit 5756e2
                    This means, while you make such a blocking call, NMClient's state
    Packit 5756e2
                    does not change. But usually you perform the synchronous call
    Packit 5756e2
                    to change some state. In this form, the blocking call is not useful,
    Packit 5756e2
                    because NMClient only changes the state after iterating the GMainContext,
    Packit 5756e2
                    and not after the blocking call returns.
    Packit 5756e2
                  

    Packit 5756e2
  2. Packit 5756e2
                    Like 1), but after making the blocking g_dbus_connection_call_sync(),
    Packit 5756e2
                    update the NMClient cache artificially. This is what
    Packit 5756e2
                    nm_manager_check_connectivity() does, to "fix" bgo#784629.
    Packit 5756e2
                    This also has the problem of out-of-order events, but it kinda
    Packit 5756e2
                    solves the problem of not changing the state during the blocking
    Packit 5756e2
                    call. But it does so by hacking the state of the cache. I think
    Packit 5756e2
                    this is really wrong because the state should only be updated from
    Packit 5756e2
                    the ordered stream of D-Bus messages. When libnm decides to modify
    Packit 5756e2
                    the state, there are already D-Bus messages queued that affect this
    Packit 5756e2
                    very state.
    Packit 5756e2
                  

    Packit 5756e2
  3. Packit 5756e2
                    Instead of calling g_dbus_connection_call_sync(), use the
    Packit 5756e2
                    asynchronous g_dbus_connection_call(). If we would use a separate
    Packit 5756e2
                    GMainContext for all D-Bus related calls, we could ensure that
    Packit 5756e2
                    while we block for the response, we iterate the internal main context.
    Packit 5756e2
                    This might be nice, because all events are processed in order and
    Packit 5756e2
                    after the blocking call returns, the NMClient state is up to date.
    Packit 5756e2
                    The are problems however: current blocking API does not do this,
    Packit 5756e2
                    so it's a significant change in behavior. Also, it might be
    Packit 5756e2
                    unexpected to the user that during the blocking call the entire
    Packit 5756e2
                    content of NMClient's cache might change and all pointers to the
    Packit 5756e2
                    cache might be invalidated. Also, of course NMClient would invoke
    Packit 5756e2
                    signals for all the changes that happen.
    Packit 5756e2
                    Another problem is that this would be more effort to implement
    Packit 5756e2
                    and it involves a small performance overhead for all D-Bus related
    Packit 5756e2
                    calls (because we have to serialize all events in an internal
    Packit 5756e2
                    GMainContext first and then invoke them on the caller's context).
    Packit 5756e2
                    Also, if the users wants this, they could implement it themself
    Packit 5756e2
                    using their own extra GMainContext and the asynchronous API.
    Packit 5756e2
                  

    Packit 5756e2
    Packit 5756e2

    Packit 5756e2
    Packit 5756e2
              See also this blog
    Packit 5756e2
              for why blocking calls are wrong.
    Packit 5756e2
            

    Packit 5756e2

    Packit 5756e2
              All possible behaviors for synchronous API have severe behavioural
    Packit 5756e2
              issues and thus such API is deprecated. Note that "deprecated" here does not
    Packit 5756e2
              mean that the API is going to be removed. Libnm does not break API. The
    Packit 5756e2
              user may:
    Packit 5756e2
    Packit 5756e2
              

    Packit 5756e2
      Packit 5756e2
    • Packit 5756e2
                      Continue to use this API. It's deprecated, awkward and discouraged,
      Packit 5756e2
                      but if it works for you, that's fine.
      Packit 5756e2
                    

      Packit 5756e2
    • Packit 5756e2
                      Use asynchronous API. That's the only sensible way to use D-Bus.
      Packit 5756e2
                      If libnm lacks a certain asynchronous counterpart, it should be
      Packit 5756e2
                      added.
      Packit 5756e2
                    

      Packit 5756e2
    • Packit 5756e2
                      Use GDBusConnection directly. There really isn't anything wrong
      Packit 5756e2
                      with D-Bus or GDBusConnection. This deprecated API is just a wrapper
      Packit 5756e2
                      around g_dbus_connection_call_sync(). You may call it directly
      Packit 5756e2
                      without feeling dirty.
      Packit 5756e2
                    

      Packit 5756e2
      Packit 5756e2

      Packit 5756e2
              

      Packit 5756e2
      Packit 5756e2
      Packit 5756e2
      Packit Service 018b0a

      Generated by GTK-Doc V1.33.0
      Packit 5756e2
      </body>
      Packit 5756e2
      </html>