Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

Wednesday, January 13, 2016

Connections in NetworkManager

Connections, as defined and used by NM, are very close to PvDs. The goal of this post is to analyse data structures/functions for connections within NetworkManager and so that plan of integrating PvDs into NM can be developed. This is done in a separate post.

A definition of connection in NetworkManager can be found in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 comment within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 libnm-core/nm-connection.c file:
An #NMConnection describes all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 settings and configuration values that are necessary to configure network devices for operation on a specific network. Connections are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fundamental operating object for NetworkManager; no device is connected without a #NMConnection, or disconnected without having been connected with a #NMConnection.

Each #NMConnection contains a list of #NMSetting objects usually referenced by name (using nm_connection_get_setting_by_name()) or by type (with nm_connection_get_setting()). The settings describe cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual parameters with which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 network devices are configured, including device-specific parameters (MTU, SSID, APN, channel, rate, etc) and IP-level parameters (addresses, routes, addressing methods, etc).
In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following text we'll see how connections are implemented in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NM code, how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are initialized and how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are accessed over cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DBus. Note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are some parts related to connections that are specific for a system/distribution on which NM is running. In that case I concentrate on how things are done on Fedora (and very likely all RHEL derivatives).

Class and interface hierarchy


The base for all connection objects in NetworkManager is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interface defined in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 files libnm-core/nm-connection.[ch]. The interface is implemented by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following classes:
  • Class NMSettingsConnectionClass defined in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 files  src/settings/nm-settings-connection.[ch].

    This class is used by NetworkManager daemon and it is exported via DBus interface.
     
  • Class NMRemoteConnectionClass defined in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 files libnm/nm-remote-connection.[ch].

    Used by clients in clients subdirectory.
     
  • Class NMSimpleConnectionClass defined in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 files libnm-core/nm-simple-connection.[ch].

    This is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object passed via DBus so it is for communicating connections from and to NetworkManager and its clients.

Accessing individual connection data stored in NetworkManager


Each connection, active or not, known to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NetworkManager is exposed through DBus on path /org/freedesktop/NetworkManager/Settings/%u where %u is a sequence number assigned to each connection. Interface implemented by each connection is org.freedesktop.NetworkManager.Settings.Connection. The interface is described in introspection/nm-settings-connection.xml file.

To invoke a method defined in interface on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given object you can use dbus-send command line tool like this:
dbus-send --print-reply --system \
    --dest=org.freedesktop.NetworkManager \
    /org/freedesktop/NetworkManager/Settings/0 \
    org.freedesktop.NetworkManager.Settings.Connection.GetSettings
In this particular case we are invoking GetSettings method on object /org/freedesktop/NetworkManager/Settings/0 which will return us its configuration parameters. Note that invoking this particular method is easy since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are no arguments to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method.

The class that represents connection, and that is answering to DBus messages, is declared in src/settings/nm-settings-connection.[ch] files. This class implements interface NM_TYPE_CONNECTION and also subclasses NM_TYPE_EXPORTED_OBJECT class.  The NM_TYPE_EXPORTED_OBJECT class has all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 methods necessary to expose cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object on DBus.

To see what functions are called when DBus methods are called take a look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source file nm-settings-connection.c. There, you'll find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following code:
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (class),
    NMDBUS_TYPE_SETTINGS_CONNECTION_SKELETON,
    "Update", impl_settings_connection_update,
    "UpdateUnsaved", impl_settings_connection_update_unsaved,
    "Delete", impl_settings_connection_delete,
    "GetSettings", impl_settings_connection_get_settings,
    "GetSecrets", impl_settings_connection_get_secrets,
    "ClearSecrets", impl_settings_connection_clear_secrets,
    "Save", impl_settings_connection_save,
    NULL);
What this code does is that it binds GBus methods to function that should be called. When we called GetSettings method, obviously that ended up in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function impl_settings_get_settings().

The first step done when processing GetSettings method is authorization check. After authorization check has succeeded, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 return message is constructed in get_settings_auth_cb() method.


Accessing and manipulating all connections in NetworkManager


NetworkManager exposes interface org.freedesktop.NetworkManager.Setting on object org.freedesktop.NetworkManager.Setting that, among ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r things, allows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user to retrieve list of all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 known connections to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NetworkManager.  To get all connections you would could use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following dbus-send command:
dbus-send --print-reply --type=method_call --system \
        --dest=org.freedesktop.NetworkManager \
        /org/freedesktop/NetworkManager/Settings \
        org.freedesktop.DBus.Properties.Get \
        string:org.freedesktop.NetworkManager.Settings \
        string:"Connections"
This would get you something like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following output:
variant array [
   object path "/org/freedesktop/NetworkManager/Settings/10"
   object path "/org/freedesktop/NetworkManager/Settings/11"
   object path "/org/freedesktop/NetworkManager/Settings/12"
   object path "/org/freedesktop/NetworkManager/Settings/13"
   object path "/org/freedesktop/NetworkManager/Settings/14"
   object path "/org/freedesktop/NetworkManager/Settings/15"
   object path "/org/freedesktop/NetworkManager/Settings/0"
   object path "/org/freedesktop/NetworkManager/Settings/1"
   object path "/org/freedesktop/NetworkManager/Settings/2"
   object path "/org/freedesktop/NetworkManager/Settings/3"
   object path "/org/freedesktop/NetworkManager/Settings/4"
   object path "/org/freedesktop/NetworkManager/Settings/5"
   object path "/org/freedesktop/NetworkManager/Settings/6"
   object path "/org/freedesktop/NetworkManager/Settings/7"
   object path "/org/freedesktop/NetworkManager/Settings/8"
   object path "/org/freedesktop/NetworkManager/Settings/9"
   object path "/org/freedesktop/NetworkManager/Settings/16"
]
The exact output will depend on your particular setup and usage.

The given interface and property is implemented by class NMSettingsClass (defined in src/settings/nm-settings.[ch]). This class implements interface NM_TYPE_CONNECTION_PROVIDED (defined in src/nm-connection-provider.[ch]). There is only one object of this class in NetworkManager and it is instantiated when NetworkManager is starting.

Looking in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file src/settings/nm-settings.c you can see at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end registration of function to be called when DBus messages are received. DBus interface of this module is defined in introspection/nm-settings.xml file. Here is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 relevant code that binds DBus methos to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 functions that implement cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m:
nm_exported_object_class_add_interface (
        NM_EXPORTED_OBJECT_CLASS (class),
        NMDBUS_TYPE_SETTINGS_SKELETON,
        "ListConnections", impl_settings_list_connections,
        "GetConnectionByUuid", impl_settings_get_connection_by_uuid,
        "AddConnection", impl_settings_add_connection,
        "AddConnectionUnsaved", impl_settings_add_connection_unsaved,
        "LoadConnections", impl_settings_load_connections,
        "ReloadConnections", impl_settings_reload_connections,
        "SaveHostname", impl_settings_save_hostname,
        NULL);
So, when we called ListConnections method, obviously that ended up in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function impl_settings_list_connections(). Here, we'll emphasize one more method, LoadConnections. This DBus method, implemented in impl_settings_load_connections(), load all connections defined in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system. We'll take a look now at that method.

Initializing connections


All network connections are loaded and initialized from two sources: system dependent network configuration and VPN configuration scripts.

System dependent network configuration


There are several types of distributions with different network configuration mechanisms. Since that part is obviously system dependent, NetworkManager has a plugin system that isolates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 majority of NetworkManager code from those system dependent parts. Plugins can be found in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 directory src/settings/plugins. Additionally, all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 plugins are based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 src/settings/plugin.[ch] base class. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case of Fedora Linux (as well as RHEL, CentOS and ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r derivatives) network configuration is recorded in scripts in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 directory /etc/sysconfig/network-scripts. and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 plugin that handles those configuration files is stored in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 directory src/settings/plugins/ifcfg-rh.

The initialization of connections stored in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 directory /etc/sysconfig/network-scripts is done when NetworkManager bootstraps and instantiates object NMSettings of type NMSettingsClass. This is performed in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function nm_manager_start() in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file src/nm-manager.c. There, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method nm_settings_start() is called on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NMSettings object which in turn first initializes all plugins (as, by default, found in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 directory /usr/lib64/NetworkManager/). It cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n calls private method load_connections() to actually load all connections. Note that in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 directory  /usr/lib64/NetworkManager/ cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are plugins of ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r types too, but only plugins that have prefix libnm-settings-plugin- are loaded. Which plugins should be loaded are can be defined in three places (lowest to highest priority):

  1. Compile time defaults, as given to configure.sh script, or, by default for RHEL type systems "ifcfg-rh,ibft" plugins.
  2. In configuration file /etc/NetworkManager/NetworkManager.conf.
  3. As specified in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command line.

Method load_connections() iterates over every defined plugin and asks each plugin for all registered connections it knows by calling a method get_connections() within a specific plugin. For RedHat type of distributions cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 plugin that handles all connections is src/nm-settings/plugins/ifcfg-rh/plugin.c and in that file function get_connections() is called. Now, if called for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first time, this function will in turn call read_connections() within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same plugin/file that will read all available connections. Basically, it opens directory /etc/sysconfig/network-scripts and builds a list of all files in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 directory. Than, it tries to open each file and only those that were parsed properly are left as valid connections. Each found connection is stored in object NMIfcfgConnection of type NMIfcfgConnectionClass. These objects are defined in files src/nm-settings/plugins/ifcfg-rh/nm-ifcfg-connection.[ch].

When all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 connections were loaded, read_connections() returns a list of all known connections to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 plugin. The function load_connections() cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n, for each connection reported by each plugin, calls claim_connection() method in nm-connection.c. This function, among ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r tasks, exports cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 connection via DBus in a form described above, in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 section Accessing individual connection data stored in NetworkManager.

VPN configuration scripts


Details about VPN connections are stored in /etc/NetworkManager/system-connections directory, one subdirectory per VPN. Those files are read by src/vpn-manager/nm-vpn-manager.c when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object is initialized and as such initialized when VPN manager is initialized. VPN manager also also monitors changes in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 VPN configuration directory and acts appropriately.

Properties of a connection


Each connection has a set of properties attached to it in a form of a key-value pairs.

Activating a connection


A connection is activated by calling ActivateConnection DBus method. This method is implemented in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NetworkManager's main class/object, NMManager. This class/object is a singleton object who's impementation is in src/nm-manager.[ch] files. Looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code that binds DBus methods to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 functions that implement cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m we can see that ActivateConnection is implemented by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function impl_manager_activate_connection(). The ActivateConnection method, and its implementation function, accept several parameters:
  1. Connection that should be activated identified by its connection path (e.g. "/org/freedesktop/NetworkManager/Settings/2").
  2. Device on which connection should be activated identified by its path (e.g. "/org/freedesktop/NetworkManager/Devices/2").
  3. Specific object?
Some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 input argument can be unspecified. To make cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m unspecified in DBus call cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y should be set to "/" and this will be translated into NULL pointer in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 impl_manager_activate_connection() function. Of all combinations of parameters (with respect to being NULL or non-NULL) cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following ones are allowed:
  1. When connection path is not specified device must be given. In that case all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 connections for that device will be retrieved and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best one will be selected. "The best one" is defined as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 most recently used one.
  2. If connection path is specified, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n device might or might not be specified. In case it is not defined cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best device for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given connection will be selected. To determine "cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best device" first list of all devices is retrieved and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n for each device status is checked (must be managed, available, compatible with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 requested connection). Note that "compatible with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 requested connection" means, for example, you can not start wireless connection on a wired connection.
There are "software only", or virtual, connections. Those are checked in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function nm_connection_is_virtual() which is implemented in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file libnm-core/nm-connection.c. When this post was written, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following connections were defined as virtual, or software only:
  • Bond
  • Team
  • Bridge
  • VLAN
  • TUN
  • IPtunnel
  • MACVLAN
  • VXLAN
Finally, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are also VPN connections that also don't have associated devices.

When all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 checks are performed, devices and connections are found, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n an object of type NMActiveConnection is created in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function _new_active_connection(). Here, in case VPN connection is started, VPN establishment is initiated and you can read more about that process in anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r post.


Sunday, January 3, 2016

Few tips about GObject for C++ programmers

While studying NetworkManager code I got more and more comfortable with OO programming retrofitted into C programming language using GObject library. At first I was confused because it is quite complex and I didn't well understand how it works. Furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rmore, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 documentation for beginners is lacking and scare. But, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 more I learned cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 more logical it seemed to me. Since I'm well acquainted with C programming language and to some extent to C++ I decided to write about OO model in GObject, NetworkManager and C based on what someone might expect from C++. As usual, this is for my later reference, but also for everyone else wanting to learn how to use or understand GObject. I'll write in a form of tips, or details you should know in order to better understand how it works.

Declaring a class


In C++ language cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are two parts of class implementation. First, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a class declaration and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a class definition. Class declaration goes into a header file (e.g. Point.h) and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re you'll find something like this:
class Point {
}
Now, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 question is how to do this in C using GObject? The process is a bit more involved due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 characteristics of a C programming language. Anyway, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 recipe is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following one. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 header file (e.g. point.h) that declares class method you would put cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following code:
#include

#define TYPE_POINT (point_get_type())

typedef struct _PointClass {
    GObjectClass parent_class;
} PointClass;

typedef struct _Point {
    GObject parent_instance;
} Point;

GType point_get_type(void);
This code declares two structures, one that will be used by a class (PointClass) and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r one for each object of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given class type (Point). You would also need to define class and object initialization functions as follows:
#include "point.h"

typedef struct _PointPrivate PointPrivate;

G_DEFINE_TYPE (Point, point, G_TYPE_OBJECT);

static void point_class_init (PointClass* klass)
{
}

static void point_init (Point* self)
{
}
Finally, you can write a main function (in e.g. main.c file) which doesn't do anything, but, nevercá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365less cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class is here. That's how you would declare a class.

The code for this example can be found on GitHub.

Final and derivable classes


The distinction between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two is that you can not subclass final class, while on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r hand, derivable classes can be sub classed. I don't want to go into discussions why final classes, but only into technical details related to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir use in GObject. GObject documentation recommends to use final classes if you can, and only cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n derivable classes. If you take a look at some ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r sources, especially for C++, you'll find doubts about benefits of final classes.

So, in C++ (at least from C++11) you would declare final class like this:
class Point final {
};
Now, if you try to subclass it:
class Point2 : public Point {
};
You'll receive compiler error due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 final keyword prohibiting class Point to be subclassed:
g++ -Wall -std=c++11 main.cpp -o main
In file included from main.cpp:1:0:
Point.h:6:7: error: cannot derive from ‘final’ base ‘Point’ in derived type ‘Point2’
 class Point2 : public Point {
       ^
Note that nothing special has to be done in order for a class to be derivable. Only if you want a class to be final you have to explicitly say so. So, what about GObject and final and derivable classes?

Two macros are used in GObject to create classes for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 purpose of creating final and derivable classes. To define final class use G_DECLARE_FINAL_TYPE macro. You should modify header file from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous example like this:
#include

#define TYPE_POINT (point_get_type())
G_DECLARE_FINAL_TYPE(Point, point, , POINT, GObject)

typedef struct _Point {
    GObject parent_instance;
} Point;
Note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is no definition of type PointClass! The reason is that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 macro G_DECLARE_FINAL_TYPE declares it. Also, point_get_type() isn't declared because G_DECLARE_FINAL_TYPE declares it. That's basically it for final class.

To declare derivable class, macro G_DECLARE_DERIVABLE_TYPE is used. In this case, as in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous, you should only change header file which should look like this:
#include

#define TYPE_POINT (point_get_type())
G_DECLARE_DERIVABLE_TYPE(Point, point, , POINT, GObject)

typedef struct _PointClass {
    GObjectClass parent_instance;
} PointClass;
This time, PointClass type is defined explicitly while Point is defined by G_DECLARE_DERIVABLE_TYPE macro.

The code for this example can be found on GitHub.

Instantiate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object of a given class


The next thing is how would you instantiate an object of some class. For sample, to instantiate an object of a class written in C++ from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous section in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main function you would do cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following:
Point* point = new Point();
To do cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same thing in C/GObject combo, you again have to do a bit more work. Actually, you have to define allocator for a class, i.e. something equivalent to a new keyword in C++. The way to create a new object of a given type is:
Point *point = someclass_new();
So, you need to define cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function someclass_new(). Our will be very simple one:
Point* point_new(void)
{
        return g_object_new(TYPE_POINT, NULL);
}
Place it at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file point.c and in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main function create an object of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Point class by calling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function point_new(). As a final note, instantiating final or derivable class is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same.

The code for this example can be found on GitHub.

Instantiate a singleton object


One feature used by NetworkManager a lot are singleton objects. Namely, some objects control system wide resources and thus cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a need to have a single object control a single resource. For example, main component of a NetworkManager is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object NM_TYPE_MANAGER and it is necessary to have only one such object. There is also a single object for a configuration held in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object/class NM_TYPE_CONFIG.

So, how is singleton object created? NetworkManager has some infrastructure that makes this task really simple. You start with a regular class/object. Then in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 C file with an object implementation you should call cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following two macros/functions:
NM_DEFINE_SINGLETON_INSTANCE (NMNetnsController);
NM_DEFINE_SINGLETON_REGISTER (NMNetnsController);
Then, in function that allocates an object, you have a variable singleton_instance that should be NULL until cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object is created and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n it should contain a pointer to a singleton object. Additionally, after creating object, you should call function nm_singleton_instance_register().

You are tasked with taking care that no new object of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given type is created, i.e. you can shoot yourself in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 foot in case you don't take care to check cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 content of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 variable singleton_instance. singleton_instance is a file global variable declared by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 macros shown above.

Private attributes


The next step is to add private attributes to our class. Let's suppose that we need to add x and y coordinates. In C++ we would modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class declaration in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following way:
class Point {
private:
        int x, y;
}
And that's basically it for C++ version. In case of C/GObject, you would define struct for private data in C file (point.c) with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following content:
typedef struct _PointPrivate PointPrivate;

struct _PointPrivate {
        int x, y;
};
First, observe that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 structure is placed in C file, not in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 header file. The reason is that this is private/internal structure so no users of a class should know cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 content of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given structure. Furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rmore, keep in mode that this structure isn't required to be called as shown in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 example by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GObject system, you can call it whatever you want, but it is a good practice and strongly suggested to add Private suffix to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object name for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 readability reasons.

Private part for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object should be allocated when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class is initialized. To achieve that add cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following line in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class initialization function, i.e. in point_class_init() function:
g_type_class_add_private (klass, sizeof (PointPrivate));
Before finishing with private attributes, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is one more thing we need to discuss, and that is how to access private part of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object. For that purpose it is good to declare cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following macro:
#define POINT_GET_PRIVATE(object)      \
          (G_TYPE_INSTANCE_GET_PRIVATE((object), TYPE_POINT, PointPrivate))
This macro takes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pointer to an object and returns pointer to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 private data of a given object. Note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last argument to G_TYPE_INSTANCE_GET_PRIVATE is type (structure definition) of a private data. So, when you have a method that accesses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object's private data you would, at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 start of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method, call cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mentioned macro to obtain pointer to private data structure and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n you would access it as usual.

The code for this example can be found on GitHub.

Public methods


After we added private attributes we want to add public methods that will allow us to get and set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 values for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given private attributes. So, in C++ we would modify Point class definition as follows:
class Point {
private:
        int x, y;
public:
        void setValue(int x, int y);
        int getx(void);
        int gety(void);
};
The public methods should be defined in a C++ file (i.e. Point.cpp):
#include "Point.h"

void Point::setValue(int x, int y)
{
        this->x = x;
        this->y = y;
}

int Point::getx(void)
{
        return this->x;
}

int Point::gety(void)
{
        return this->y;
}
And, obviously, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 methods would be used in a following way in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main function:
point->setValue(1, 1);
std::cout << "x=" << point->getx() << ", y=" << point->gety() << std::endl;
Now, to achieve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same with GObject system several changes to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 existing C code are necessary. First, we'll define a helper macro in a C file (point.c) that we will use to obtain private data of an object of class Point:
#define POINT_GET_PRIVATE(object)      \
          (G_TYPE_INSTANCE_GET_PRIVATE((object), TYPE_POINT, PointPrivate))
Next, public methods are just global functions with a prefix of a object name and with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first argument being cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pointer to an object of a given class. In our case, we have three public methods each with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following prototype:
void point_set_value(Point *point, int x, int y);
int point_get_x(Point *point);
int point_get_y(Point *point);
Those declaration should go into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 header file (point.h) because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are accessible to any user of object Point, while cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir definitions should go into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 C file (point.c):
void point_set_value(Point* point, int x, int y)
{
        PointPrivate* priv = POINT_GET_PRIVATE(point);

        priv->x = x;
        priv->y = y;
}

int point_get_x(Point* point)
{
        PointPrivate* priv = POINT_GET_PRIVATE(point);

        return priv->x;
}

int point_get_y(Point* point)
{
        PointPrivate* priv = POINT_GET_PRIVATE(point);

        return priv->y;
}
Finally, you should use those public methods after object of class Point is allocated in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main function. Here is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 example:
point_set_value(point, 1, 1);
printf("x=%d, y=%d\n", point_get_x(point), point_get_y(point));
And that's it. The code for this example can be found in GitHub repository.

Virtual methods


The methods implemented using GObject in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous section are non-virtual public methods. They are easy to implement, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 least flexible. So, to implement public virtual methods in GObject we need to:
  1. In class structure (PointClass) add function pointer for each virtual method we need.
  2. In header file declare dispatcher methods that will be called by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class.
  3. Define dispatcher methods in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source file.
  4. Define implementation of virtual methods in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source file.
  5. Initialize function pointers with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation of virtual methods.
Here are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 steps in more details with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 concrete example of Point class. Before continuing, note that virtual methods are possible only in derivable classes, not in final!

Step 1 is to add function pointer fields in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class structure. That means that you class structure definition has to have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following format:
typedef struct _PointClass
{
        GObjectClass parent_class;
        void (*set_value) (Point *self, int x, int y);
        int (*get_x) (Point *self);
        int (*get_y) (Point *self);
} PointClass;
Note cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bold parts, those are function pointer that will point to implementation of virtual methods. Each method takes, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first argument, pointer to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object it has to act upon.

Step 2 is to declare dispatcher methods. Those are very similar to non-virtual public methods in appearance, i.e. cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 name consists of a object name prefix and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function name. Again, this is recommended, not something that is mandated by GObject system. Anyway, in our case those are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lines you have to add to header file:
void point_set_value(Point* self, int x, int y);
int point_get_x(Point* self);
int point_get_y(Point* self);
Step 3 is to define dispatcher methods in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source file. I'll do it only for one method, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 rest are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same. So, in case of point_set_value() it would look like this:
void point_set_value(Point* self, int x, int y)
{
PointClass *klass;
klass = _POINT_GET_CLASS(self);
klass->set_value(self, x, y);
}
As you can see, what cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method does is it access class definition, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n invokes appropriate function through its pointer. I have to stress here two things:
  1. I skipped assertions, i.e. if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object/classes are of right type!
  2. Note cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 leading underscore in _POINT_GET_CLASS. It is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 consequence of skipping module name when calling G_DECLARE_DERIVABLE_TYPE macro, i.e. I skipped third argument!
So, any user of a class will call those public methods which will dispatch cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 real method.

In step 4 we have to define implementation of virtual methods in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source file. Again, I'll show it only for a single method. Also, you'll note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same as for non-virtual public methods. Only we have to call cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m differently so that compiler can differentiate between different function. I decided to use prefix objectname_private_, but it is my choice. I didn't manage to find something recommended by GObject. So, here it goes for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function to set value:
void point_private_set_value(Point* self, int x, int y)
{
PointPrivate *priv = POINT_GET_PRIVATE(self);
priv->x = x;
priv->y = y;
}
Finally, step 5 is to initialize pointers to dispatchers which in turn will call real methods. This has to be done by modifying definition of PointClass structure (or class structure in general). Here is how this structure should look like:
static void
point_class_init (PointClass* klass)
{
g_type_class_add_private (klass, sizeof (PointPrivate));
klass->set_value = point_private_set_value;
klass->get_y = point_private_get_y;
klass->get_x = point_private_get_x;

}
Note that we have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 part that adds private data for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 objects. The bold parts are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ones that initialize virtual functions.


Inheritence and subclassing


Inheritance allows for specialization of some class without touching that class internals. It is one of very important OO mechanisms and as such it is also supported in GObject and used by, e.g. NetworkManager.

So, suppose we want to define 3D point by basing its implementation on Point class while in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same time adding only z coordinate. In C++ we would declare new class and say explicitly that we inherit base class Point:
#include "Point.h"

class Point3D: public Point
{
private:
        int z;
public:
        void setValue(int x, int y, int z);
        int getz(void);
}
As you can see we include declaration of 2D point and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n we add third coordinate as well as new methods, one to retrieve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 third coordinate and anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r one to be able to set all three coordinates. There is also definition (i.e. implementation) of a new class which is placed in Point3D.cpp file:
#include "Point3D.h"

void Point3D::setValue(int x, int y, int z)
{
        Point::setValue(x, y);
        this->z = z;
}

int Point3D::getz(void)
{
        return this->z;
}
Note how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base class method is called, by prefixing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method name with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base class name.

As usual, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 question is how this is done in C using GObject library. First, GObject make distinction between final and derivable classes, as we already saw above. Base class must be derivable, while subclass might be eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r final or derivable.

So, we are going to define derivable class Point as follows:
#include

#define TYPE_POINT (point_get_type())
G_DECLARE_DERIVABLE_TYPE(Point, point, , POINT, GObject)

typedef struct _PointClass {
        GObjectClass parent_class;
} PointClass;

Point* point_new(void);

void point_set_value(Point *point, int x, int y);
int point_get_x(Point *point);
int point_get_y(Point *point);
This is almost cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same as original Point declaration we had. The implementation part isn't changed. Now, Point3D is declared as follows:
#include
#include "point.h"

#define TYPE_POINT3D (point3d_get_type())
G_DECLARE_FINAL_TYPE(Point3D, point3d, , POINT3d, Point)

typedef struct _Point3D {
        Point parent_instance;
} Point3D;

Point3D* point3d_new(void);

void point3d_set_value(Point3D* point, int x, int y, int z);
int point3d_get_z(Point3D* point);
Note cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last parameter in G_DECLARE_FINAL_TYPE is Point. Basically, that's cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base class and up until now we had cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re GObject from which all object descend.

Defining and implementing interfaces


Interfaces in OO languages are used as a form of a contract between different components. Some languages, as Java for example, have direct support for defining interfaces, while ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rs, like C++, don't have and instead use some indirect methods. Here I would like to show how interfaces are implemented in GObject and for that purpose I'll declare interface that will be implemented by Point class used so far for examples. We'll start with C++, as usual.

To define interface in C++ abstract classes are used. Abstract class can not be instantiated because it has at least one pure virtual method that needs to be implemented by subclass. So, here is how interface for Point class would look like in C++:
class PointInterface {
public:
virtual void setValue(int x, int y) = 0;
virtual int getx(void) = 0;
virtual int gety(void) = 0;
};
As you can see, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pure virtual method is declared by having "equal zero" addition. Now, just one more change is necessary and that is to declare that Point class implements this interface/abstract class. To do that only a single change is necessary, i.e.:
class Point : public PointInterface { ... }
In ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r words, Point inherits PointInterface.

So, how to do this in GObject? Here is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 official documentation and we are going to do this for our existing Point class.

TBC...

Constructor


In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous examples we already saw constructors, class constructor (*_class_init) and object constructor (*_init). Class constructor is called only once, when a first object of a given class is instantiated. Object constructor, on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r hand, is called every time an object of a given class is instantiated. You can easily see this modifying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous example so that you place printf() statements into appropriate constructors (point_class_init() for a class constructor and point_init() for an object constructor). Then, by creating two objects of a Point class you'll clearly see that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class constructor is called only once, while cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object constructor is called as many times as you instantiated objects.

Destructor


Destructor isn't necessary



Object/class initialization and removal

When creating a new object using g_object_new() function cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a certain sequence of steps executed. For an object that is first of its class, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sequence is:

  1. _class_init()
  2. constructor()
  3. constructed()
  4. _init()

Of those four, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first and fourth, are mandatory and have to be defined in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source. The second and third steps are optional and you define cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m in class constructor (_class_init()) by assigning appropriate pointers to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class interface.

Note that g_object_new() accepts an object type that should be created and a sequence of attribute-value pairs terminated with a single NULL. Those attribute-value pairs are used to set properties of an object (installed using g_object_class_install_property() function) but only after object constructor finishes. Also, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 additional requirement is to define set_property class method that will be called to set each property.

For objects of next type only object constructor is called and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n properties are initialized.

When object is removed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n its destructor is called, if it exists. If this is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last object of its class, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n finalize method is called, again, if it exists.

Name spaces


TBD


Literature

If you try to Google for GObject examples or tutorials you'll find some materials from Gnome Web site. But, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 truth is that those tutorials leave some open questions and it is really hard to find something else. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end I managed to find some references that I think are very valuable so here cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are:

Saturday, January 2, 2016

Processing RA messages in NetworkManager

The goal of this post is to analyze processing of RA messages through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NetworkManager code, starting with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial reception all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 way through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 assignment of parameters to a device through which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RA was received. As a special case will also take a look what happens when RS is sent, i.e. what is different in comparison to unsolicited RAs. But first, we'll take a look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 relevant code organization and initialization process.

Code to process RAs and initialization phase


For receiving RA and sending RA NetworkManager uses libndp library. This library is used in class NM_TYPE_LNDP_RDISC (defined in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file src/rdisc/nm-lndp-rdisc.c) which is a platform specific class tailored for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Linux OS. This class inherits from class NM_TYPE_RDISC (defined in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file src/rdisc/nm-rdisc.c) which is a platform independent base class. It contains functionality that is platform independent so cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365oretically NetworkManager can be more easily ported to, e.g. FreeBSD.

To create a new object of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type NM_TYPE_LNDP_RDISC it is necessary to call function nm_lndp_rdisc_new(). This is, for example, done by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class NM_DEVICE_TYPE in function addrconf6_start() for each device for which IPv6 configuration is started.

Now, if NetworkManager will use RAs or not depends on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 configuration setting for IPv6 that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user defines. If you go to configuration dialog for some network interface cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a setting for IPv6 configuration which might be ON or OFF. In case it is OFF, no IPv6 configuration will be done. If IPv6 configuration is enabled (switch placed in ON state) cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 specific configuration methods should be selected. The selected option is checked in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function src/devices/nm-device.c:act_stage3_ip6_config_start(), where, depending on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 option selected, a specific initialization is started:
  • Automatic (method NM_SETTING_IP6_CONFIG_METHOD_AUTO)

    Start full IPv6 configuration by calling src/devices/nm-device.c:addrconf6_start() function.
     
  • Automatic, DHCP only (method NM_SETTING_IP6_CONFIG_METHOD_DHCP)

    Only configuration based on DHCP parameters received will be done. This type of configuration is initiated by calling function src/devices/nm-device.c:dhcp_start().
     
  • Manual (method NM_SETTING_IP6_CONFIG_METHOD_MANUAL)

    Manual configuration using parameters specified in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 configuration dialog and nothing else. The configuration of this type is initiated by calling function nm_ip6_config_new() which returns appropriate IPv6 configuration object.
     
  • Link-local Only (method NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)

    Initiate only a link-local address configuration by calling function src/devices/nm-device.c:linklocal6_start().
Since in this post we are concerned with RA processing than we are obviously interested only in Automatic configuration type, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 one that calls addrconf6_start() function. This function, in turn, calls function src/nm-device.c:linklocal6_start() to ensure that link local configuration is present. It might happen that link local address isn't configured and so RA configuration must wait, or link local configuration is still present. In eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r case, when link local configuration is present RA processing can start. RA processing is kicked off by calling src/nm-device.c:addrconf6_start_with_link_ready() which in turn calls src/nm-rdisc.c:nm_rdisc_start() to kick off RA configuration.

nm_rdisc_start() is called with a pointer to NM_LNDP_RDISC class (defined in src/rdisc/nm_lndp_rdisc.c). Note that a method (nm_rdisc_start()) from a base class (NM_RDISC_TYPE, defined in src/rdisc/nm_rdisc.c) is called with a pointer to a subclass of a NM_RDISC_TYPE! Method in a base class does cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following:
  1. Checks that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a subclass which defined virtual method start() (gassert(klass->start)).
  2. Initializes timeout for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 configuration process. If timeout fires, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n rdisc_ra_timeout_cb() will be called that emits NM_RDISC_RA_TIMEOUT signal.
  3. Invokes a method start() from a subclass. Subclass is, as already said, NM_LNDP_RDISC and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given method registers a callback src/rdisc/nm-lndp-rdisc.c:receive_ra() with libndp library. The callback is called by libndp library whenever RA is received.
  4. Starts solicit process by invoking solicit() method. This method schedules RS to be sent in certain amount of time (variable next) by send_rs() method. This method, actually, invokes send_rs() method from a subclass (src/nm-rdisc/nm-rdisc-linux.c:send_rs()) which sends RS using libndp library. Note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 number of RSes sent is bounded and after certain amount of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m sent cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process is stopped under cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 assumption that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is no IPv6 capable router on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 network.
  5. After RA has been received and processed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 application of configuration parameters is done in src/device/nm-device.c:rdisc_config_changed() method. This callback is achieved by registering to NM_RDISC_CONFIG_CHANGED signal that is emitted by src/rdisc/nm-rdisc.c class whenever IPv6 configuration changes.
So, in conclusion, when link local configuration is finished, RA processing is started. The RA processing consists of waiting for RA in src/rdisc/nm-lndp-rdisc.c:receive_ra(). If RA doesn't arrive is certain amount of time cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n RS is sent in function src/nm-rdisc/nm-rdisc-linux.c:send_rs().

RA processing


When RA is received it is processed by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function src/rdisc/nm-lndp-rdisc.c:receive_ra(). The following configuration options are processed from RA by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given function:
  1. DHCP level.
  2. Default gateway.
  3. Addresses and routes.
  4. DNS information (RDNSS option).
  5. DNS search list (DNSSL option).
  6. Hop limit.
  7. MTU.
All cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 options that were parsed are stored (or removed from) a private attributes of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base object (NMRDisc defined in src/rdisc/nm-rdisc.h).

Finally, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method src/nm-rdisc.c:nm_rdisc_ra_received() is called to cancel all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 timeouts. It will also emit signal NM_RDISC_CONFIG_CHANGED that will trigger application of received configuration parameters to a networking device.

Processing RS/RA


The RS/RA processing differs only by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fact that RS is sent after certain amount of time has passed and RA wasn't received, as described in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Code to process RAs and initialization phase section. After RS is sent, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RA processing is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same as it would be without RS being sent.

Applying IPv6 configuration data


Application of received IPv6 configuration data is done in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method src/device/nm-device.c:rdisc_config_changed(). IPv6 configuration is stored in IPv6 configuration object NM_TYPE_IP6_CONFIG defined in src/nm-ip6-config.c.

Note that this isn't cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 real application of configuration data, but only that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 configuration data is stored in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 appropriate object.

The function that really applies configuration data is src/devices/nm-device.c:ip6_config_merge_and_apply().

Tuesday, December 29, 2015

NetworkManager and OpenVPN - How it works?

I spent a lot of time trying to figure out how NetworkManager works. Very early in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process I came to conclusion that NM is a very complex piece of a software while in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same time documentation is lacking. What adds to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 complexity is GObject mechanism that tries to fit object oriented programming into C programming language. So, in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end, I decided to write everything I managed to learn. First, in that way I'm leaving notes for myself later. In addition, I hope I'll help someone and thus save someone's time.

NetworkManager


As a first goal to understand NetworkManager I set to understand how NM manages VPN connections. The following sequence of steps is a result of a research to answer cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given question. Note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 flow isn't complete, but is enough to understand mechanics of VPN establishment. In addition, note that all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given file pathnames are relative to NetworkManager git repository.

So, everything starts when user activates VPN. At that moment a message is sent via DBus by nm-applet, nmcli or some ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r mechanism cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following happens:
  1. Message to activate VPN sent via cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DBus ends up in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function src/nm-manager.c:impl_manager_activate_connection().
  2. The function src/nm-manager.c:impl_manager_activate_connection() calls function src/nm-manager.c:_new_active_connection().
  3. Function _new_active_connection() function creates a new object of a type NM_TYPE_ACTIVE_CONNECTION, i.e. new active connection. To create new active connection object a method src/vpn-manager/nm-vpn-connection.c:nm_vpn_connection_new() in this particular case is used. This triggers a chain of initialization events described later.
  4. After cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object is created a control returns to impl_manager_activate_connection() where asynchronous authorization check is initiated. Callback function to call when authorization check finishes is src/nm-manager.c:_activation_auth_done().
  5. After authorization is done cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 callback function _activation_auth_done() is called which in turn, if everything is OK, calls function src/nm-manager.c:_internal_activate_generic() which in turn calls function src/nm-manager.c:_internal_activate_vpn().
  6. The function _internal_activate_vpn() calls cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function src/vpn-manager/nm-vpn-manager.c:nm_vpn_manager_activate_connection() is called.
  7. The function src/vpn-manager/nm-vpn-manager.c:nm_vpn_manager_activate_connection() calls function src/vpn-manager/nm-vpn-connection.c:nm_vpn_connection_activate().
  8. The function nm_vpn_connection_activate() connects asynchronously to DBus and when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 connection is made a callback function on_proxy_acquired() is called.
  9. The function on_proxy_acquired() connects to signal "notify::g-name-owner" and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n calls src/vpn-manager/nm-vpn-connection.c:nm_vpn_service_daemon_exec(). The purpose of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function nm_vpn_service_daemon_exec() is to start plugin binary (nm-openvpn-service).

    The goal of connecting to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 signal "notify::g-name-owner" is to receive notification when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service appears, i.e. when it is initialized and available over cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DBus so that appropriate signals can be registered. The most important registered signals, in our case, are Ip4Config and Ip6Config. When cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function on_proxy_acquired() connects callback functions to DBus signals cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process of establishing VPN can be continued so it also calls cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function src/vpn-manager/nm-vpn-connection.c:get_secrets().
  10. The function get_secrets() calls function nm_settings_connection_get_secrets() and registers a callback src/vpn-manager/nm-vpn-connection.c:get_secrets_cb().
  11. The function src/vpn-manager/nm-vpn-connection.c:get_secrets_cb() sends secrets to VPN plugin via DBus. The send process is asynchronous and when finished callback src/vpn-manager/nm-vpn-connection.c:plugin_need_secrets_cb() is called.
  12. The callback function src/vpn-manager/nm-vpn-connection.c:plugin_need_secrets_cb() calls function src/vpn-manager/nm-vpn-connection.c:really_activate().
  13. The function src/vpn-manager/nm-vpn-connection.c:plugin_need_secrets_cb() calls Connect method on VPN plugin via DBus interface. Since DBus call is asynchronous callback function is registered, src/vpn-manager/nm-vpn-connection.c:connect_cb(). Callback function just calls src/vpn-manager/nm-vpn-connection.c:connect_success() that clears all timers.
The call to Connect method mentioned in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last step above initiates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chain of events in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 VPN plugin described in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next section that, in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end, results in real connection establishment. When VPN connection is established, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 VPN plugin will send three signals: Config, Ip4Config and Ip6Config. Those signals are caught by callbacks config_cb(), ip4_config_cb() and ip6_config_cb() respectively. Those signals, when activated, will be caught in nm-vpn-connection.c (look at step 9 in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous list).


OpenVPN plugin


VPN plugins for NetworkManager are written so that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y inherit some base classes from Network Manager and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y only have to implement code specific to a particular VPN, while generic parts are implemented by NetworkManager  and placed in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base class. For example, DBus interface that each plugin has to implement is common to all of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m and thus implemented in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base class. This is classic OO programming paradigm. But, in this case OO paradigm is emulated in C so when you start to study cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code of some specific plugin, at first sight nothing will make sense and it will be hard to grasp what happens, where and when. So, before I describe sequence of events, I'll describe a code structure first as it aids a lot in understanding cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code.

Static code structure and plugin initialization


The main part of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NetworkManager OpenVPN plugin is in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file src/nm-openvpn-service.c. This file inherits a class defined in libnm/nm-vpn-service-plugin.c from NetworkManager. Additionally, VPN DBus interface is defined in NetworkManager source in file introspection/nm-vpn-plugin.xml.

So, when you build OpenVPN plugin, a new binary is created, nm-openvpn-service. When NetworkManager executes this plugin its main method is invoked. In main method, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 most important line is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following one:
plugin = nm_openvpn_plugin_new (bus_name);
That line causes new object of type NM_TYPE_OPENVPN_PLUGIN to be instantiated. Looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function nm_openvpn_plugin_new() nothing special can be seen at a first glance. Basically, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is only cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following line:
plugin = (NMOpenvpnPlugin *)
    g_initable_new (NM_TYPE_OPENVPN_PLUGIN,
                    NULL, &error,
                    NM_VPN_SERVICE_PLUGIN_DBUS_SERVICE_NAME,
                    bus_name,
                    NULL);
But, because GObject type system is in background, actually a lot of things happen. First, initialization methods/constructors of OpenVPN plugin class and objects are called (nm_openvpn_plugin_init() and nm_openvpn_plugin_class_init()). Also, initialization methods/constructors of base class are called (nm_vpn_service_plugin_class_init() and nm_vpn_service_plugin_init()).

In addition, base class nm-vpn-service-plugin defines an interface that is initialized separately from class and object. The mechanism used is described here.

Note that after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 plugin is initialized, NetworkManager receives information about this via a signal notify::g-name-owner in src/vpn-manager/nm-vpn-connection.c. This causes src/vpn-manager/nm-vpn-connection.c to connect to DBus interface and starts cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sequence of steps described in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following subsection.

VPN activation sequence of steps


In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following code, when I write base class I mean on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file libnm/nm-vpn-plugin-service.c in NetworkManager. When I write OpenVPN class or OpenVPN service cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n I'm thinking on file src/nm-openvpn-service in network-manager-openvpn code.

The following sequence of steps is initiated by calling method Connect on VPN plugin via DBus:
  1. DBus signal initiates a function impl_vpn_service_plugin_connect() in base class. This function is registered as a handler for DBus Connect method serviced by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 plugin in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function init_sync() in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base class. If you look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given function you'll notice that it only transfers control to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function _connect_generic() in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base class.
  2. The function _connect_generic() does some checks and transfers function to OpenVPN class, i.e. cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method real_connect() is called in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file src/nm-openvpn-service.c.
  3. The method real_connect() just redirects control to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function _connect_common().
  4. The method _connect_common() does some sanity check, obtains some parameters, and calls method nm_openvpn_start_openvpn_binary().
  5. The method nm_openvpn_start_openvpn_binary() searches for openvpn binary on a local file system, constructs command line options based on preferences set for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 VPN connection and from environment variables, and finally starts openvpn binary (call to function g_spawn_async()). One important part of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command line construction is that openvpn binary is told not to assign parameters itself, but to call helper scripts and pass it all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parameters. This helper script is nm-openvpn-service-openvpn-helper contained in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 src directory of networkmanager-openvpn-plugin. So, when OpenVPN binary establishes VPN connection it calls helper script.

    It also registers two callbacks. The first one monitors process using a g-child-watch-source-new() function. A callback function is 
    openvpn_watch_cb() that, if called, assumes an error occurred or openvpn binary just finished. The second callback is timer that, when fires, calls function nm_openvpn_connect_timer_cb(). It only tries to connect to OpenVPN's management socket. So, in ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r words, notification about successful VPN establishment to OpenVPN plugin isn't done using GLib or DBus notification system, but just by waiting and checking. As a final note, timer isn't used in every case. Actually, it seems that it is used rarely, only when aucá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ntication type is static key.
  6. The nm-openvpn-service-openvpn-helper script, in its main function, collects all network related data from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 environment (set by openvpn binary) and sends it via DBus to nm-openvpn-service using methods SetConfig, SetIp4Config and SetIp6Config.
  7.  The configuration is caught by functions impl_vpn_service_plugin_set_config()impl_vpn_service_plugin_set_ip4_config(), and impl_vpn_service_plugin_set_ip6_config() in VPN plugin base class. Those function, in turn, call functions nm_vpn_service_plugin_set_config()nm_vpn_service_plugin_set_ip4_config() and nm_vpn_service_plugin_set_ip6_config(). They also call finish DBus proxies so that helper script can continue executing after each call.
  8. Each of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 functions nm_vpn_service_plugin_set_config()nm_vpn_service_plugin_set_ip4_config() and nm_vpn_service_plugin_set_ip6_config() does two things. It emits signal ("config", "ip4-config" and "ip6-config") from base class and OpenVPN class. [Note: I don't fully understand this mechanism yet]

Literature

It seems to me that it is very hard to come up with a good documenation that describes this topic. So, here are some better references I used:

  1. For signals cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best reference I could find was from Maemo 4 documentation, available on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following link: http://maemo.org/maemo_training_material/maemo4.x/html/maemo_Platform_Development_Chinook/Chapter_04_Implementing_and_using_DBus_signals.html

Sunday, March 23, 2014

Two or more applications listening on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same (IP, port) socket

It might happen that you need two applications to listen to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same (IP, port) UDP socket with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 idea that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 applications know how to differentiate between packets that are intended for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m. If this is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n you'll have to do something special because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel doesn't allow two, or more, applications to bind in such a way. As a side note, starting with kernel 3.9 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a socket option SO_REUSEPORT that allows multiple applications to bind to a single port (under certain preconditions) but it doesn't work cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 way I described here.

One solution is to have some kind of a demultiplexer application, i.e. it binds to a given port, receives packets and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n sends cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m to appropriate application. This will work, but it wasn't appropriate for my situation. So, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 solution is that one application binds to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given port, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r uses PF_PACKET socket with appropriate filter so that it also receives UDP packets of interest. I hope that you realize that this works only for UDP, and not for TCP or ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r connection oriented protocols!

So, what you have to do is:

  1. Open appropriate socket with socket() system call.
  2. Bind to interface using bind() system call.
  3. Attach filter to socket using setsockopt().
  4. Receive packets.

If you want an example of how this is done, take a look into busybox, more specifically its udhcpc client.

Now, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are two problems with this approach that you need to be aware of. The first is that if you try to send via this socket you are avoiding routing code in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel! In ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r words, it might happen that you try to send packets to wrong directions. How this can be solved, and if it really needs solution, depends on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 specific scenario you are trying to achieve.

The second problem is that if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is no application listening on a given port, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel will sent ICMP port unreachable error messages on each received UDP message. I found a lot of questions on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Internet about this issue, but without any real answer. So, I took a look at where this error message is generated, and if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is anything that might prevent this from happening.

UDP packets are received in function __udp4_lib_rcv() that, in case cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is no application listening on a given port, sends ICMP destination port unreachable message. As it turns out, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 only case when this message will not be sent is if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 destination is multicast or broadcast address. So, your options are, from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 most to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 least preferred:

  1. Be certain that you always have application listening on a given port.
  2. Use iptables to block ICMP error messages (be careful not to block too much!).
  3. The application on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r end ignores those error messages.

Thursday, December 27, 2012

UDP Lite...

Many people know for TCP and UDP, at least those that work in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 field of networking or are learning computer networks in some course. But, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 truth is that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rs too, e.g. SCTP, DCCP, UDP Lite. And all of those are actually implemented in Linux kernel. What I'm going to do is describe each one of those in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following few posts and give examples of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir use. In this post, I'm going to talk about UDP Lite. I'll assume that you know UDP and also that you know how to use socket API to write UDP application.

UDP Lite is specified in RFC3828: The Lightweight User Datagram Protocol (UDP-Lite) . The basic motivation for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 introduction of a new variant of UDP is that certain applications (primarily multimedia ones) want to receive packets even if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are damaged. The reason is that codecs used can recover and mask errors. UDP itself has a checksum field that covers cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 whole packet and if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is an error in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet, it is silently dropped. It should be noted that this checksum is quite weak actually and doesn't catch a lot of errors, but nevercá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365less it is problematic for such applications. So, UDP lite changes standard UDP behavior in that it allows only part of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet to be covered with a checksum. And, because it is now different protocol, new protocol ID is assigned to it, i.e. 136.

So, how to use UDP Lite in you applications? Actually, very easy. First, when creating socket you have to specify that you want UDP Lite, and not (default) UDP:
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDPLITE);
Next, you need to define what part of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet will be protected by a checksum. This is achieved with socket options, i.e. setsockopt(2) system call. Here is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function that will set how many octets of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet has to be protected:
void setoption(int sockfd, int option, int value)
{
    if (setsockopt(sockfd, IPPROTO_UDPLITE, option,
            (void *)&value, sizeof(value)) == -1) {
        perror("setsockopt");
        exit(1);
    }
}
It receives socket handle (sockfd) created with socket function, option that should be set (option) and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 option's value (value). There are two options, UDPLITE_SEND_CSCOV and UDPLITE_RECV_CSCOV. Option UDPLITE_SEND_CSCOV sets cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 number of protected octets for outgoing packets, and UDPLITE_RECV_CSCOV sets at least how many octets have to be protected in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 inbound packets in order to be passed to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 application.

You can also obtain values using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following function:
int getoption(int sockfd, int option)
{
  int cov;
  socklen_t len = sizeof(int);
  if (getsockopt(sockfd, IPPROTO_UDPLITE, option,
  (void *)&cov, &len) == -1) {
  perror("getsockopt");
exit(1);
}
return cov;
}
This function accepts socket (sockfd) and option it should retrieve (i.e. UDPLITE_SEND_CSCOV or UDPLITE_RECV_CSCOV) and returns cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 option's value. Note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two constants, UDPLITE_SEND_CSCOV or UDPLITE_RECV_CSCOV, should be explicitly defined in your source because it is possible that glibc doesn't (yet) define cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m.

I wrote fully functional client and server applications you can download and test. To compile cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m you don't need any special options. So that should be easy. Only change you'll probably need is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IP address that clients sends packets to. This is a constant SERVER_IPADDR which contains server's IP address hex encoded. For example, IP address 127.0.0.1 is 0x7f000001.

Finally, I have to say that UDP Lite will probably have problems traversing NATs. For example, I tried  it on my ADSL connection and it didn't pass through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NAT. What I did is that I just started client with IP address of one of my servers on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Internet, and on that server I sniffed packets. Nothing came to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server. This will probably be a big problem for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 adoption of UDP Lite, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time will tell...

You can read more about this subject on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Wikipedia page and in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Linux manual page udplite(7).

About Me

scientist, consultant, security specialist, networking guy, system administrator, philosopher ;)

Blog Archive