How to suppress multiple netlink events? - c

I have been using this code as a sample to receive interface up/down events on a Linux machine. I am able to receive the events correctly but when an interface comes up from a previous down state, I receive multiple netlink events like this:
Event received >> NETLINK::Down
Event received >> NETLINK::Down
Event received >> NETLINK::Up
edit: I have modified a line in this code from:
addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
to:
addr.nl_groups = RTMGRP_LINK;
But still I receive multiple events. Can anybody suggest if it is possible to suppress these events to receive a unique event for each state? If so how?

Finally after a lot of research I was able to get this done. There is a flag called "ifi_change" which gives out the change in the Netdevice's state change. I wasn't able to think of it because the rtnetlink man page did not mention anything about it. It says it is reserved for future use and should always be set to 0xFFFFFFFF. However, its value changes upon change in the current state of the interface. If there is a state change it gives a finite value else it is zero. Using this check I was able to suppress multiple netlink messages.

Looking at the code, I suspect you're getting a notification for each of the following types of events:
addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
I'd suggest narrowing it down to
addr.nl_groups = RTMGRP_LINK;
(or to IPv4/IPv6 as appropriate.)

Related

EVFILT_WRITE returning twice

I'm trying to send a buffer to my socket client when the file descriptor is available for writing.
EV_SET is set to: EVFILT_WRITE, EV_ADD | EV_DISABLE | EV_CLEAR
then when changed to EVFILT_WRITE, EV_ENABLE then EVFILT_WRITE get triggered once which is great!
but if i use the function write or send when i get EVFILT_WRITE like this:
if (e->filter == EVFILT_WRITE)
send(socket, buff, strlen(buff), 0);
then i get again another EVFILT_WRITE event. It seems like the send function trigger another EVFILT_WRITE event. is that expected behaviour? I thought EVFILT_WRITE triggers only when the file descriptor is available for writing.
I searched for the issue, but it looks like nobody mention that. Can someone please confirm if that is expected behaviour and why?
This is how I understand it:
Since you used EV_CLEAR, the kevent facility starts to return state transitions, not the current state. So, whenever you touch the socket descriptor with kevent() or send() calls, you get an EVFILT_WRITE event back.
Another way to look at this:
When send() is called the descriptor becomes unavailable for writing for a moment and then again becomes available, which is why you get an event.
I'll try to loop in some knowledgeable people to this question.

Dbus structure and method calls in C

I am starting to create a dbus application in C to interface with bluez. I am new to dbus and I am a little confused as how to correctly structure my application with dbus.
The first question is related to the Service, Interface, and Object path in dbus. Bluez Adapter API has the org.bluez service, a org.bluez.Adapter1 interface, and a number of methods and properties. If I wanted to call the void StopDiscovery() method, would the following be the correct call?
DBusPendingCall * pending;
// create a new method call and check for errors
msg = dbus_message_new_method_call("org.bluez",
"/", // object to call on
"org.bluez.Adapter1", // interface to call on
"StopDiscovery"); // method name
// send message and get a handle for a reply
if (!dbus_connection_send_with_reply (m_dbus_conn, msg, &pending, -1))
{
//err
}
If this is the case, when does the object path come into play?
The follow on to this is how to go about receiving information back from dbus. I've seen a few examples with a DBusPendingCall * however the function has dbus_pending_call_block() so the function blocks until the data is returned. If I wanted to do multiple calls and not block I would need to make a list of DBPendingCall pointers and check each one? Are there any callbacks?
Thanks
I did create an example showing the non-blocking call based on the dbus watch and timeout mechanism, in response to the SO question dbus watch and timeout examples. Basically you run a unix select() loop and everything is dispatched around it.
And I did not touch the multiple outstanding pending-call part. I assume one way is to check each pending-call to see whether it is completed when the watched event is received. Checking pending complete is non-blocking. If you keep a small number of outstanding pending calls it should be ok, though that is not an efficient solution if the number becomes big.
It looks like according to the API document, a better solution is to use dbus_pending_call_set_notify() to register a callback to a pending call.
So it appears that both the object path and the interface are required when talking to bluez over dbus.
// create a new method call for the adapter
msg = dbus_message_new_method_call("org.bluez",
"/org/bluez/hci0", // object to call on
"org.bluez.Adapter1", // interface to call on
"StopDiscovery"); // method name
// create a new method call for a characteristic on
// a given service
msg = dbus_message_new_method_call("org.bluez",
"/org/bluez/hci0/dev_12_34_56_78_9A_BC/service0010/char0011",
"org.bluez.GattCharacteristic1",
"StartNotify");
The select on Unix sockets for pending looks like a solid, scaleable way to go, I will consider this architecture as the application grows

How to obtain value of socket filter handle (sflt_filter.sf_handle) from apple site for registering packet filtration

I am trying to obtain handle key for socket-filter for registering packet filtration. I have already register it for TCP packets now I want to register it for UDP packet. This handle key needs to be unique from another applications.
sflt_filter.sf_handle = 0xAACAF333;
I have obtained it before about 2 years ago using the link (http://developer.apple.com/datatype/) but it get redirected to different link now.
I have read the link it says that Creator Codes are ignored by 10.6 and above. But for implementing kext for packet-filtration we need that code to be unique.
Does any one know how to obtain the unique key?
OR it is not required to obtain the unique key?
OR their is different way to use handle now?
Thanks in advance.
I know the question is very outdated, but I faced the same problem, and just for next one who will too:
now you can register and obtain unique handle for filter calling kev_vendor_code_find function from sys/kern_event.h, passing bundle id and pointer to uint32 variable.
After that, in user space you can get this handle by SIOCGKEVVENDOR ioctl, passing pointer to kev_vendor_code structure with same bundle id in vendor_string field.
You should not do any things to "unregister" this handle (but you should unregister the filter with this handle in driver::stop() )

Not sure to understand why my server receives "channelInterestChanged" events in the frame decoder

I implemented my own frame decoder to parse the bytes received through a UDP socket (using NioDatagramChannelFactory and ConnectionlessBootstrap) according to our protocol.
Just to follow what is happening in the server while receiving messages, I added trace logs in each callback method of the decoder.
It appears that for almost every message the server receives, we can see that the event "channelInterestChanged" is received twice in the method channelInterestChanged(). The value of the event is first 0 (OP_NONE) then 1 (OP_READ).
I read the documentation about this, but I am still not sure to understand why I receive such events. I first through it was because the receive buffer (or the selector queue) was full, but the server receives this event the same number of times it receives the "messageReceived" event (before the decode() method is called) and all the messages/frames are properly decoded as expected. When messages are missing, I do no see any event at all. In this case it is probably because the receive buffer of the datagram socket is full. But even if I increase this receive buffer, I continue to see these events and to miss messages.
So, I am wondering why for each message received, the server also receives two "channelInterestChanged", one with the OP_NONE value and one with the OP_READ value. Please, takes note also that in the channel pipeline, after my frame decoder, there is an ExecutionHandler and another business-specific handler (which sends a JMS message to an ActiveMQ instance).
Any idea or explanation for me?
Thank you.
When a DownStreamChannelStateEvent fired from a handler (e.g calling channel.setReadable(), channel.setWriteable()), the event will change the channel's nio selector key's interested option in the NioDatagramWorker, later, a UpstreamChannelStateEvent will be fired with changed option (i.e OP_READ or OP_NONE)
Your frame decoder handler receives UpstreamChannelStateEvents because, some other handlers in the pipeline are changing the channel's read interest options (the purpose of calling channel.setReadable/setWriteable is, throttling the read/write to avoid congestion, OutOfMemoryError in the application).
If you have any MemoryAwareThreadPoolExecutor in your pipeline (which monitors the size of the channel memory used), it may suspend or resume reading by calling channel.setReadable() any time if the channel receives messages too fast. You may have to configure the MATPE instance with optimum maxChannelMemorySize, maxTotalMemorySize or disable it by setting it to 0.

Can I Send to Socket and receive from it in the same place in C

I have a dll written in C.
I would like to send data to a socket and receive the answer in the same function.
e.g.:
BOOL SendToSocketAndRecv(...)
{
// ...
send(...);
retval = recv(...);
// ...
}
In another word, my dll should not follow Client Server pattren.
Is this possible ?
any help ?
Thank you - Khayralla
Yes
You may work in either blocking (synchronous) or non-blocking (asynchronous) mode. Depending on this you may or may not send more data before you receive something from the peer.
"Stream" sockets (like TCP) are "tunnels". If the peer sends several packets you may receive them in a single call to recv, and vice-versa - a sinle "message" from the peer may take several calls to recv. Hence you should read the message in a loop.
You have a lot to learn about network programming.
I am sending a commands to Robot and then wait to get answer
Yes, what you have will work.
But things start to get interesting when you factor in the chance that the robot will not respond for whatever reason. Then you need to provide for a timeout on the response. Soon other things start to creep in. For example, you may not want to be stuck in the read for the duration of the wait, because you may need to service other events (user input or other sources) as they comes in.
A common architecture to handle this is to use select() and make it the hub of all your incoming events. Then you drive a state machine (or machines) off these events. You end up with an event driven architecture. It would look something like this:
while(true)
{
select(fds for event sources, timeout);
if (timeout)
{
call robot state machine(timeout);
continue;
}
iterate through fds
{
if (fd has data)
{
read data into buf
if (fd is for robot)
{
call robot state machine(buf)
}
else if (fd is for source1)
{
call source1 state machine(buf)
}
...
}
}
}
In this model, sends can be done from anywhere in the code. But you wind up sitting in the select() after, waiting for events. Also, you will have to figure out the details of doing the correct timeout and select in general, but there is enough of that out there.
Yes this is both possible and legal. The API itself isn't concerned about being used from the same function.
not only is this possible, it is a classic coding idiom for a client in a client server system. Usually the function is called something like ExecuteRequest

Resources