C++ library for receiving network interface up/down notification with interface name on Ubuntu - dbus

This post has two questions.
1. network interface up/down notification on a specific network device
2. list the network devices.
See below for the answers provided by me. (Thanks to Velkan for helping me in arriving at this)
I am looking for a c++ library which receives the network interface up/down event notification with interface name on Ubuntu machine. I have been asked by my colleagues to use dbus interfaces for the same. Used the link below for the same, which just notifies about any interface up/down event without interface name.
https://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/examples/C/glib/monitor-nm-state-gdbus.c
I am googling around for a quite sometime now, I could not find right examples and even the dbus documentation is not straight forward or not providing the information what I am looking for.
Any help on this would be greatly helpful.
Thanks in Advance

I've looked a bit with the d-feet utility.
On the 'System Bus' there is an /org/freedesktop/NetworkManager with a DeviceAdded signal.
The /org/freedesktop/NetworkManager/Devices/1 things have:
Interface string in org.freedesktop.NetworkManager.Device
Carrier boolean and PropertiesChanged signal in org.freedesktop.NetworkManager.Device.Wired, org.freedesktop.NetworkManager.Device.Bridge, org.freedesktop.NetworkManager.Device.Adsl...
So, get the NetworkManager object, listen to the modifications to the device lists, subscribe to the PropertiesChanged of the current devices and devices that will appear, watch for the Carrier property.
Look into other properties if you want to detect that the interface is up, but has no IP assigned (or maybe it's in some other intermediate state).
If you're using the Server version of Ubuntu (you're not) then I think that it doesn't use the NetworkManager, so it has a somewhat less usable D-Bus interface - org.freedesktop.network1.
Shell example of DeviceAdded/DeviceRemoved:
$ dbus-monitor --system "type='signal',interface='org.freedesktop.NetworkManager'"
When a Wi-Fi USB key is plugged in:
signal time=1509615532.227067 sender=:1.8 -> destination=(null destination) serial=2051 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=DeviceAdded
object path "/org/freedesktop/NetworkManager/Devices/10"
signal time=1509615532.228150 sender=:1.8 -> destination=(null destination) serial=2056 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=PropertiesChanged
array [
dict entry(
string "AllDevices"
variant array [
object path "/org/freedesktop/NetworkManager/Devices/0"
object path "/org/freedesktop/NetworkManager/Devices/1"
object path "/org/freedesktop/NetworkManager/Devices/2"
object path "/org/freedesktop/NetworkManager/Devices/3"
object path "/org/freedesktop/NetworkManager/Devices/4"
object path "/org/freedesktop/NetworkManager/Devices/5"
object path "/org/freedesktop/NetworkManager/Devices/6"
object path "/org/freedesktop/NetworkManager/Devices/8"
object path "/org/freedesktop/NetworkManager/Devices/10"
]
)
dict entry(
string "Devices"
variant array [
object path "/org/freedesktop/NetworkManager/Devices/0"
object path "/org/freedesktop/NetworkManager/Devices/1"
object path "/org/freedesktop/NetworkManager/Devices/2"
object path "/org/freedesktop/NetworkManager/Devices/3"
object path "/org/freedesktop/NetworkManager/Devices/4"
object path "/org/freedesktop/NetworkManager/Devices/5"
object path "/org/freedesktop/NetworkManager/Devices/6"
object path "/org/freedesktop/NetworkManager/Devices/8"
object path "/org/freedesktop/NetworkManager/Devices/10"
]
)
]
signal time=1509615533.253596 sender=:1.8 -> destination=(null destination) serial=2072 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=PropertiesChanged
array [
dict entry(
string "WirelessEnabled"
variant boolean false
)
]
signal time=1509615533.287235 sender=:1.8 -> destination=(null destination) serial=2080 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=PropertiesChanged
array [
dict entry(
string "ActiveConnections"
variant array [
object path "/org/freedesktop/NetworkManager/ActiveConnection/3"
object path "/org/freedesktop/NetworkManager/ActiveConnection/2"
object path "/org/freedesktop/NetworkManager/ActiveConnection/1"
object path "/org/freedesktop/NetworkManager/ActiveConnection/0"
]
)
]
Several signals are fired. So, if we were subscribed to the DeviceAdded or PropertiesChanged, we can deduce that we need to watch the device #10 too.
When it's removed:
signal time=1509615612.892305 sender=:1.8 -> destination=(null destination) serial=2086 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=DeviceRemoved
object path "/org/freedesktop/NetworkManager/Devices/10"
signal time=1509615612.893697 sender=:1.8 -> destination=(null destination) serial=2089 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=PropertiesChanged
array [
dict entry(
string "ActiveConnections"
variant array [
object path "/org/freedesktop/NetworkManager/ActiveConnection/3"
object path "/org/freedesktop/NetworkManager/ActiveConnection/2"
object path "/org/freedesktop/NetworkManager/ActiveConnection/1"
object path "/org/freedesktop/NetworkManager/ActiveConnection/0"
]
)
dict entry(
string "AllDevices"
variant array [
object path "/org/freedesktop/NetworkManager/Devices/0"
object path "/org/freedesktop/NetworkManager/Devices/1"
object path "/org/freedesktop/NetworkManager/Devices/2"
object path "/org/freedesktop/NetworkManager/Devices/3"
object path "/org/freedesktop/NetworkManager/Devices/4"
object path "/org/freedesktop/NetworkManager/Devices/5"
object path "/org/freedesktop/NetworkManager/Devices/6"
object path "/org/freedesktop/NetworkManager/Devices/8"
]
)
dict entry(
string "Devices"
variant array [
object path "/org/freedesktop/NetworkManager/Devices/0"
object path "/org/freedesktop/NetworkManager/Devices/1"
object path "/org/freedesktop/NetworkManager/Devices/2"
object path "/org/freedesktop/NetworkManager/Devices/3"
object path "/org/freedesktop/NetworkManager/Devices/4"
object path "/org/freedesktop/NetworkManager/Devices/5"
object path "/org/freedesktop/NetworkManager/Devices/6"
object path "/org/freedesktop/NetworkManager/Devices/8"
]
)
]
signal time=1509615612.910829 sender=:1.8 -> destination=(null destination) serial=2095 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=PropertiesChanged
array [
dict entry(
string "WirelessEnabled"
variant boolean true
)
]
Same signals: #10 has disappeared.
Or subscribe to DeviceAddedand DeviceRemoved to be getting only them:
$ dbus-monitor --system type=signal,interface=org.freedesktop.NetworkManager,member=Device{Added,Removed}

Anyone who wants a working code sample, can replace similar line given below, in the link shared in the question (https://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/examples/C/glib/monitor-nm-state-gdbus.c).
Code snippet for listening up/down event on a specific device
Here I have just changed the object path parm value to
/org/freedesktop/NetworkManager/Devices/0
/org/freedesktop/NetworkManager/Devices/1
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
flags,
NULL, /* GDBusInterfaceInfo /
"org.freedesktop.NetworkManager",
"/org/freedesktop/NetworkManager/Devices/1",
"org.freedesktop.NetworkManager.Device",
NULL, / GCancellable */
&error);
Code snippet for list the devices available.
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
flags,
NULL, /* GDBusInterfaceInfo */
"org.freedesktop.NetworkManager",
"/org/freedesktop/NetworkManager",
"org.freedesktop.NetworkManager",
NULL, /* GCancellable */
&error);
ret = g_dbus_proxy_call_sync (proxy,
"GetDevices",
NULL,
G_DBUS_CALL_FLAGS_NONE, -1,
NULL, &error);
if (!ret) {
g_dbus_error_strip_remote_error (error);
g_print ("ListConnections failed: %s\n", error->message);
g_error_free (error);
return;
}
g_variant_get (ret, "(^ao)", &paths);
g_variant_unref (ret);
for (i = 0; paths[i]; i++)
g_print ("%s\n", paths[i]);
Output for list of network devices (I have 2 nic cards in my machine)
/org/freedesktop/NetworkManager/Devices/0
/org/freedesktop/NetworkManager/Devices/1

Related

add an array to a specific dictionary object

So I'm working on a dictionary to build a json schema.
Using a recursive function which works pretty well when appending properties to these objects.
However, I want to add an array to the object properties.
So for this I've attached the following code as an example:
import json
dataProp = (
['airplane', 'fly'],
['car', 'drive'],
['boat', 'sail'],
['airplane', 'pilot'],
['car', 'driver'],
['boat', 'sailer']
)
dataReqProp = (
['airplane', 'fly'],
['boat', 'sail'],
['car', 'driver'],
['boat', 'sailer']
)
obj = {'transportation': {'airplane': {}, 'car': {}, 'boat': {}}}
def update_panel_json(obj, target_key, update_value, json_type):
if isinstance(obj, dict):
for key, value in obj.items():
if key == target_key:
obj[key].setdefault(json_type, {}).update(update_value)
update_panel_json(value, target_key, update_value, json_type)
elif isinstance(obj, list):
for entity in obj:
update_panel_json(entity, target_key, update_value, json_type)
for key, prop in dataProp:
new_prop = {prop: {"type": "string"}}
json_type = 'properties'
update_panel_json(obj, key, new_prop, json_type)
for key, prop in dataReqProp:
new_prop = {prop}
json_type = 'required'
update_panel_json(obj, key, new_prop, json_type)
# obj['transportation']['airplane']['required'] = ['test', 'test2','test3']
#Format dictionary to JSON format
jsonSchema = json.dumps(obj)
pretty_json = json.loads(jsonSchema)
print (json.dumps(pretty_json, indent=2))
In the code there are two arrays.
The first array results in a list of objects in the dictionary.
The second array contains the same objects but with only required properties.
When doing this in the example I get the following error:
ValueError: dictionary update sequence element #0 has length 3; 2 is required
I know that this has something to do with giving more than one value to the update function of the array.
However I want to get something like this:
in the required object for each separate object:
airplane object
"required": ["fly"]
boat object
"required": ["sail"]
and so on
In case there are more properties required for one object it should be added to this same array. For instance
boat object
"required": ["sail","row"]
How do I resolve this error issue?

Access JSON Array without array name

I have a JSON object:
{
"login_name":"hello#gmail.com",
"login_pass":"abc123",
"created_on":"2021-01-17 19:20:07",
"user_id":"1",
"active":"1"
}
I don't know how to access it because it doesn't have a name.
This is using Volley:
val jsonObjectRequest = JsonObjectRequest(Request.Method.GET, url, null,
{ response ->
val obj = JSONObject(response.toString()) // this works and outputs the JSON object
val test: JSONObject = obj.getJSONObject("login_name") // this doesn't work
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
},
{ error ->
Toast.makeText(this#Login, "Error!", Toast.LENGTH_LONG).show()
}
)
I also tried converting the Json object to an array but that didn't work either...
Looked at:
Get JSONArray without array name, How can i write Android Json parsing without array name
EDIT:
val obj = JSONObject(response)
That didn't work for me because:
None of the following functions can be called with the arguments supplied.
(String!) defined in org.json.JSONObject
((MutableMap<Any?, Any?>..Map<*, *>?)) defined in org.json.JSONObject
(JSONTokener!) defined in org.json.JSONObject
But after 2 days of trying, this worked... Didn't think I could just do that
val test = response.getString("login_name")
response is indeed a jsonObject, you could use it without know its name:
String login_name= response.getString("login_name");
You are all most doing it right. Ass i see you convert the object to a string, and thats why you cant access the data afterwards.
val jsonObjectRequest = JsonObjectRequest(Request.Method.GET, url, null,
{ response ->
val obj = JSONObject(response) // this works and outputs the JSON object
val test: JSONObject = obj.getJSONObject("login_name") // this doesn't work
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
},
{ error ->
Toast.makeText(this#Login, "Error!", Toast.LENGTH_LONG).show()
}
)
Try this, without the toString() function on response.

Dynamically fetching the Json key value in Lua

I have an input Json for which I need to get the value for a specific key. Key name will be dynamic and will be passed in input like below -
Input Json -
{
"error": "Bad Request"
"source": [
{
"code": "400",
"message": "Missing values"
}
]
}
Here I need to get the value for code and message dynamically. I am able to read the values if I give the path directly like below -
json_body["source"][1].code
But here json path will be passed by user in input as string like below -
local path = "source[1].code"
How can I use this path variable value and get the Json value for this key. I tried below but its not working -
json_body[path]
Below is the sample Lua code which I am using -
local cjson = require("cjson.safe").new()
local function read_json_body(body)
if body then
return cjson.decode(body)
end
end
local json_body = read_json_body(buffered_data)
local message_path = "source[1].code"
local value = json_body[message_path]
I am able to get the values for the fields which are outside of array like below -
local message_path = "error"
local value = json_body[message_path]
As suggested by #EgorSkriptunoff below code worked -
local value = assert(load("return "..path, nil, "t", json_body))()

whisper on private network. subscribe error

I'm use THIS GUIDE for start Testing the Whisper node (geth) on private network.
Version Geth: /v1.6.7-stable-ab5646c5. Version Whisper: 5.
Start with this command :geth --shh --testnet --nodiscover console.
Connect to the test node: admin.addPeer("enode://d25474361659861e9e651bc728a17e807a3359ca0d344afd544ed0f11a31faecaf4d74b55db53c6670fd624f08d5c79adfc8da5dd4a11b9213db49a3b750845e#52.178.209.125:30379")
In answer get true
Try Case Receive Asymmetrically Encrypted Messages
Generate a key pair, and save its ID.
> id = shh.newKeyPair()
"f87747702c8d4dc9b9abf889e77ca9bf36d9f87b23fcc3ed09ff1976e52ce4d3"
Retrieve and save public key.
> shh.getPublicKey("f87747702c8d4dc9b9abf889e77ca9bf36d9f87b23fcc3ed09ff1976e52ce4d3")
"0x04ea9a8e0fc1d831e4dc094e2769989a82f3094ff774e133ec733cf9940b7c73792ab634883ef1cdf17be2f6081571dbac98c2c73e3362420e6ab53c7687a82079"
And try subscribe to messages, encrypted with certain public key.
> f = shh.subscribe({type: 'asym', key: id})
Error: Invalid number of input parameters
at web3.js:3094:20
at web3.js:4931:15
at web3.js:4974:5
at web3.js:4998:23
at <anonymous>:1:5
Parameters for Subscribe:
type string
key string
sig string
minPoW float64
topics [][]byte
allowP2P bool
Create Public Key for sig:
> var pubk = shh.getPublicKey(id)
And try this command:
> f = shh.subscribe({type: 'asym', key: id, sig: pubk, minPoW: 1, topics: ['0x07678231'], allowP2P: true})
Error: Invalid number of input parameters
at web3.js:3094:20
at web3.js:4931:15
at web3.js:4974:5
at web3.js:4998:23
at <anonymous>:1:5
But I get the same error. Internet search on this error did not yield results. How to fix this behavior?

"Unable to find any mappings for the given content, keyPath=null" RestKit 0.2

So I switched to using RestKit 0.2 and CoreData and I've been having a lot of trouble trying to get the mappings correct... I don't understand why. The JSON Response of my server is like this:
{
"meta":
{
"limit": 20,
"next": null,
"offset": 0,
"previous": null,
"total_count": 2
},
"objects":
[{
"creation_date": "2012-10-15T20:16:47",
"description": "",
"id": 1,
"last_modified":
"2012-10-15T20:16:47",
"order": 1,
"other_names": "",
"primary_name": "Mixing",
"production_line": "/api/rest/productionlines/1/",
"resource_uri": "/api/rest/cells/1/"
},
{
"creation_date": "2012-10-15T20:16:47",
"description": "",
"id": 2,
"last_modified": "2012-10-15T20:16:47",
"order": 2, "other_names": "",
"primary_name": "Packaging",
"production_line": "/api/rest/productionlines/1/",
"resource_uri": "/api/rest/cells/2/"
}]
}
Then in XCode I have:
RKObjectManager *objectManager = [RKObjectManager sharedManager];
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
objectManager.managedObjectStore = managedObjectStore;
RKEntityMapping *cellMapping = [RKEntityMapping mappingForEntityForName:#"Cell" inManagedObjectStore:managedObjectStore];
cellMapping.primaryKeyAttribute = #"identifier";
[cellMapping addAttributeMappingsFromDictionary:#{
#"id": #"identifier",
#"primary_name": #"primaryName",
}];
RKResponseDescriptor *responseCell = [RKResponseDescriptor responseDescriptorWithMapping:cellMapping
pathPattern:#"/api/rest/cells/?format=json"
keyPath:#"objects"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptorsFromArray:#[responseCell, responseUser, responseCompany]];
[managedObjectStore createPersistentStoreCoordinator];
NSString *storePath = [RKApplicationDataDirectory() stringByAppendingPathComponent:#"AppDB.sqlite"];
NSString *seedPath = [[NSBundle mainBundle] pathForResource:#"SeedDatabase" ofType:#"sqlite"];
NSError *error;
NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:storePath fromSeedDatabaseAtPath:seedPath withConfiguration:nil options:nil error:&error];
NSAssert(persistentStore, #"Failed to add persistent store with error: %#", error);
// Create the managed object contexts
[managedObjectStore createManagedObjectContexts];
// Configure a managed object cache to ensure we do not create duplicate objects
managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
My request is:
[[RKObjectManager sharedManager] getObjectsAtPath:#"/api/rest/cells/?format=json" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
RKLogInfo(#"Load complete: Table should refresh...");
[[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:#"LastUpdatedAt"];
[[NSUserDefaults standardUserDefaults] synchronize];
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
RKLogError(#"Load failed with error: %#", error);
}];
And I always get the following error:
**Error Domain=org.restkit.RestKit.ErrorDomain Code=1001 "Unable to find any mappings for the given content" UserInfo=0x1102d500 {DetailedErrors=(), NSLocalizedDescription=Unable to find any mappings for the given content, keyPath=null}**
Thanks a lot!
UPDATE: I have added cellMapping.forceCollectionMapping = YES;
but still no luck :(!
UPDATE #2: Following Blake's advice, I tried to change the path and it worked! I did /api/rest/cells/ instead of /api/rest/cells/?format=json and my server returned me everything and the mapping was successful!
Now the only problem I get is the following error:
2012-11-21 14:48:49.414 App[3125:617] W restkit.object_mapping:RKMapperOperation.m:176 Collection mapping forced but mappable objects is of type '__NSCFArray' rather than NSDictionary
It sounds like the response descriptor is failing to match for the URL requested. Two ideas:
Try removing the path pattern entirely (pass in nil) and just using a key-path based match on 'cells'
Try using a path pattern of '/api/rest/cells'
The next thing I would try is using the debugger to step through the matching. Within RKObjectManager a list of candidate response mapping is built by the RKFilteredArrayOfResponseDescriptorsMatchingPath function. If your expected response mapping is not being returned in there, then the request path to path pattern is failing to evaluate.
If things look good there, the next place a mismatch could occur is in RKResponseMapperOperation within the buildResponseMappingsDictionary method. This method evaluates the response against each response descriptor. If the response is failing to match against your response descriptor, then you'll get unexpected results here.
The final place to check is within RKResponseMapperOperation. This takes the mappings from matched descriptors and applies them. The RKMapperOperation main method should contain the deserialized response you expect and the appropriate mappings on the mappingsDictionary property.
Even when the setup seems to be right, the mapping is wrong. The information your mapping is calling is nested inside the given objects, so you've to tell the mapping to look up the values inside of the objects.
RKEntityMapping *cellMapping = [RKEntityMapping mappingForEntityForName:#"Cell" inManagedObjectStore:managedObjectStore];
cellMapping.primaryKeyAttribute = #"identifier";
[cellMapping mapKeyOfNestedDictionaryToAttribute:#"objects"];
[cellMapping mapFromKeyPath:#".id" toAttribute:"identifier"];
[cellMapping mapFromKeyPath:#"primary_name" toAttribute:"primaryName"];
For more information check the RKObjectMapping Reference.

Resources