MCNearbyServiceAdvertiser delegate methods never called - multipeer-connectivity

Implementing an app with automatic connection between devices to exchange small bunch of data, using Multi-peer Connectivity framework and Nearby Services (both browser and advertiser).
I built a Session Manager handling all connections details. Its delegate is a View Controller in order to handle updates of UI when data are received.
The Session Manager builds:
A Service Advertiser, the delegate being the Session Manager
A Service Browser, the delegate being also the Session Manager
Launching the app on two devices (one under Xcode to get the logs, the other one stand alone), I receive a Found Peer message through Service Browser delegate corresponding method.
As stated in another message, I compare the displayName property of MCPeerID (both local and from received Peer) to decide whichever of both will send invitation, thus avoiding cross-invitations.
As stated on another message here, I have also added the "optional" MCSession delegate method - (void)session:didReceiveCertificate:fromPeer:certificateHandler:
However, delegate method (void)advertiser:didReceiveInvitationFromPeer:withContext:invitationHandler: of MCNearbyServiceAdvertiser is never called. There is only a NotConnected message received by the MCSession delegate method (void)session:peer:didChangeState:after the timeout setup in the invitePeer:toSession:withContext:timeout:method.
In the various options proposed:
Session is initialized with security nil and MCEncryptionNone;
discoveryInfo are nil;
context sent in the invitation is just a short string archived as NSData.
To troubleshoot:
I have checked that all items were existing (session and its delegate, advertiser and its delegate).
Service Browser and Advertiser are never stopped, as long as app is active.
I don't know where to look over now!

Make sure that the MCpeerID you use for your local peer is the same for both the discovery and invitation phases.
I had a structure with a separate session manager to the connect/transfer worker. I made the mistake of initialising a new MCpeerID in the worker to create a session prior to the invitation, resulting in the same behaviour.
Passing the MCpeerID and MCNearbyServiceBrowser to the worker to create the session and invite fixed the issue.

Related

ActiveMQ CMS: Can messages be lost between creating a consumer and setting a listener?

Setting up a CMS consumer with a listener involves two separate calls: first, acquiring a consumer:
cms::MessageConsumer* cms::Session::createConsumer( const cms::Destination* );
and then, setting a listener on the consumer:
void cms::MessageConsumer::setMessageListener( cms::MessageListener* );
Could messages be lost if the implementation subscribes to the destination (and receives messages from the broker/router) before the listener is activated? Or are such messages queued internally and delivered to the listener upon activation?
Why isn't there an API call to create the consumer with a listener as a construction argument? (Is it because the JMS spec doesn't have it?)
(Addendum: this is probably a flaw in the API itself. A more logical order would be to instantiate a consumer from a session, and have a cms::Consumer::subscribe( cms::Destination*, cms::MessageListener* ) method in the API.)
I don't think the API is flawed necessarily. Obviously it could have been designed a different way, but I believe the solution to your alleged problem comes from the start method on the Connection object (inherited via Startable). The documentation for Connection states:
A CMS client typically creates a connection, one or more sessions, and a number of message producers and consumers. When a connection is created, it is in stopped mode. That means that no messages are being delivered.
It is typical to leave the connection in stopped mode until setup is complete (that is, until all message consumers have been created). At that point, the client calls the connection's start method, and messages begin arriving at the connection's consumers. This setup convention minimizes any client confusion that may result from asynchronous message delivery while the client is still in the process of setting itself up.
A connection can be started immediately, and the setup can be done afterwards. Clients that do this must be prepared to handle asynchronous message delivery while they are still in the process of setting up.
This is the same pattern that JMS follows.
In any case I don't think there's any risk of message loss regardless of when you invoke start(). If the consumer is using an auto-acknowledge mode then messages should only be automatically acknowledged once they are delivered synchronously via one of the receive methods or asynchronously through the listener's onMessage. To do otherwise would be a bug in my estimation. I've worked with JMS for the last 10 years on various implementations and I've never seen any kind of condition where messages were lost related to this.
If you want to add consumers after you've already invoked start() you could certainly call stop() first, but I don't see any problem with simply adding them on the fly.

JMX Notifications from MBean not listened/subscribed.What happens to the Notifications?

I am using JMX MBeans in spring 4 framework. I handle notifications from JMX mBean and process them as events.
For testing alternate approach, I just commented out notification handling part. This implies that my JMX Mbean continues to publish notifications and I am just ignoring them.
P.S:
I handle the JMX notifications via logstash. For testing I have commented out Logstash configuration
What happens to the Notification? Where it will be stored?
Will it impact memory /pile up in application?
JMX notifications are an implementation of the observer pattern. With this pattern, events are not stored, so there is no memory issue.
NotificationBroadcaster JavaDoc:
When an MBean emits a notification, it considers each listener that has been added with addNotificationListener and not subsequently removed with removeNotificationListener. If a filter was provided with that listener, and if the filter's isNotificationEnabled method returns false, the listener is ignored. Otherwise, the listener's handleNotification method is called with the notification...
See also
https://en.m.wikipedia.org/wiki/Observer_pattern
https://docs.oracle.com/javase/7/docs/api/javax/management/NotificationBroadcaster.html
Java Management Extensions (JMX) - Best Practices
Lapsed Listener Problem
The observer pattern link refers to this problem. To be clear, this potential memory link is different than what you worried about originally (storing notifications). This memory leak is caused by listeners not being deregistered, for example the logstash listener. If a listener is not deregistered, then it may not be garbage collected.
If you are concerned about this, you need to confirm that commenting out the logstash configuration prevents the listener from ever registering in the first place (it probably does). Regardless, this is probably not an issue for you, because it is just one listener object. Your concern about notifications was more serious because notifications are continuously created.
After some debugging of code flow of sendNotification Method in Java:
My findings below:
Flow of sendNotification Method:
org.springframework.jmx.export.notification.ModelMBeanNotificationPublisher
javax.management.modelmbean.RequiredModelMBean (Sendnotification)
javax.management.NotificationBroadcasterSupport
Method in NotificationBroadcasterSupport sends notifications to listeners which are registered only (based on listenersList within the class file). If no listeners are registered, then it skips sending notifications.
Hence from this I assume/conclude that Notifications are not stored anywhere.
As #DavidS suggested, if we fail to removeNotificationListener after registering and do not want to receive notifications, we would end up listeners processing notifications. Possible cause of memory leak.

CoreBluetooth on Mac ( OS X Yosemite) : Huge data receving delay after first time connection

I've got a strange problem using CoreBluetooth on Mac mini. By design, my code should receive a data update notification after discovering a characteristics service once it's connected. The problem is no data will be updated if a event is triggered by hardware within very first 20 seconds.
I've test the same code in the iOS,but it all works fine without any dealy. So the question is:
Does Apple delay the -[didUpdateValueForCharacteristic:] notification after first BLE connection?
In addition, I am using a custom profile ( A self defined UUID).
Thanks.
According to documentation:
This method is invoked when your app calls the
readValueForCharacteristic: method, or when the peripheral notifies
your app that the value of the characteristic for which notifications
and indications are enabled (via a successful call to
setNotifyValue:forCharacteristic:) has changed.
So no, it's not guaranteed that this method will be called after discovering a characteristic. You either have to call readValueForCharacteristic or subscribe to notifications and wait until peripheral sends a notification.
However, after discovering a characteristic, you can get its value in peripheral:didDiscoverCharacteristicsForService:error: method.

Recover Callback channel after CommunicationObjectAbortedException thrown

We have (Multiple)Clients-(One)Server architecture for poker desktop game. We are using callback Notifications using callback Channels.
But sometimes because of internet connection drops, that particualr client gets disconected from server and that particular's client's WCF channel is also gone to faluted state and his callback Channel which lies in server is also faluted.
Scenario :
That client is playing game, while internet connection drops, that game is stopped, still his game window remains open and when his/her internet connection gets back that client is dropped out from Server, but that player's game window still opens and that player can't do anything as his/her WCF channel is dropped out.
We want to close that particular client's window while he/she is dropped out from server and throwing 'CommunicationObjectAbortedException ' exception.
We can't use previous WCF channel's callback channel as it's in faluted state.
So we have tried to create new callbackChannel in server while dropping using below code :
OperationContext.Current.GetCallbackChannel();
but here Current is showing "NULL" as that player's WCF channel is aborted, so it's throwing an error that "Object reference not set to an instance of object".
So is there any solution to use aborted WCF channel's callback Channel or recover that WCF channel without reinitializing them or to call that client using new channel?
I'd try following:
On server side, when trying to communicate using faulted / aborted chanel - you'll failed.
Catch this failure, and remove its callback from the list (I suppose you manage some callback list).
On client side - when chanel Faulted / ... handled - try to re-open new chanel to server. When this new chenel will be open, on server side place this new callback back to the "valid callbacks" list.

How to send request from server to client using GKSession?

I want to know how can I send request from server to client using GKSession?
The reference class for GKSession say the following:
- (void)connectToPeer:(NSString *)peerID withTimeout:(NSTimeInterval)timeout Parameters peerID The string that
identifies the peer to connect to.
timeout The amount of time to wait before canceling the connection
attempt.
Discussion
When your application is acting as a client, it calls this method to
connect to an available peer it discovered. When your application
calls this method, a request is transmitted to the remote peer, who
chooses whether to accept or reject the connection request.
What should I use if I am server?
As a server you make yourself available for client connections with
peer2peerSession.available = YES;
Here is an example of creating a GKSession instance as a server:
[[GKSession alloc] initWithSessionID:sessionID displayName:#"Chris" sessionMode : GKSessionModeServer];
Here is an example of how to create a GKSession as a client:
[[GKSession alloc] initWithSessionID:sessionID displayName:#"Angel" sessionMode : GKSessionModeClient];
GKSessionModePeer will create a GKSession instance that will both advertise itself as a server, and at the same time look for advertising servers (in other words act as a client searching for servers).
You then need to set a delegate for your GKSession object, after-which the delegate needs to implement the following delegate method:
- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState : (GKPeerConnectionState)state
Within the above method you will receive messages from the session that a device has become available, became unavailable, connected, etc.
To send a request:
[_session connectToPeer:peerID withTimeout:_session.disconnectTimeout];
To accept a request:
[_session acceptConnectionFromPeer:peerID error:&error];
There is a lot of code involved and the best tutorial for you to understand everything is located here: Simple Card Playing game using GKSession