Client GKSession think it's connected after denyConnectionFromPeer - ios

I have a typical GKSessionModeServer/GKSessionModeClient setup.
When the server denies a client connection attempt with denyConnectionFromPeer:, the client's session:connectionWithPeerFailed: method is called, but then it receives a GKPeerStateConnected state change with my server's peerID. In other words the client thinks the connection succeeded while the server does not.
This seems to be at odds with common sense and the documentation for connectToPeer:withTimeout:, which says
If the connection to the remote peer is successful, the delegate’ session:peer:didChangeState: method is called for each peer it successfully connected to. If the connection fails or your application cancels the connection attempt, the session calls the delegate’s session:connectionWithPeerFailed:withError: method.
I know this doesn't say that the state change callback won't be called in the case of a connection failure, but the net result from the client's point of view is that a failed connection appears to result in a successful connection.
Clutching at straws I tried calling cancelConnectToPeer from the connectionWithPeerFailed callback, without result.
The client could work around this by ignoring the next GKPeerStateConnected, but this is kludgey and complicates reconnecting when the server starts accepting connections again.
So why can't the client session understand that it's over?

I have designed the same kind of application myself (GKSessionModeServer/GKSessionModeClient).
When you refuse the connection to a peer, it will trigger the session:peer:didChangeState: delegate, with the GKPeerConnectionState argument set to GKPeerStateDisconnected.
You just need to handle this properly in your code - I've never had any issue with that part whatsoever.

Related

NodeMCU resest with mqtt.client:close()), or mqtt.client:connect()

I have an application that uses mqtt for communication between modules and with a mobile terminal.
In some situations when the messages do not arrive, the node performs a self test of MQTT (sending a msg to itself), and when the selftest fails, tries to reconnect to the broker (mqtt offline not always arrives). And then two problems may arise:
If I perform a mqtt.client:close() to assure that the client is closed (to avoid the second problem) and the client is already closed, the node resets.
If I perform a mqtt.client:connect() and the client is still connected, an exception and a restet occurs.
is there a way to know if the mqtt client is connected or not?
Thanks for your comment. I am going to describe what I am doing, to see if you can help me:
I have two independent system, a master and a slave. The master publish a test message every 10 minutes. If there is no answer from the slave. it publish a test message to itself. If this self test does not arrive, a disconnection from the broker is assumed, and a reconnection is initiated.
And here is where the problem comes, sometimes the client is disconnected and everything go well, but sometimes it is still connected but unresponsive, and the node resets with an exception "already connected".
Performing a mqtt:close() previously to the reconnection, should be safe, but if I send it and the client is truly disconnected, the node resets without any reason (known to me).
All this is happening without receiving any offline message.
Instead of waiting for messages manually sent by the master client (which could fail to send for various reasons, leading a listening device to the wrong conclusion about the state of its connection to the broker), I recommend using MQTT's built-in connection management.
First, you can make sure that each client's initial connection has succeeded by including an error handler in :connect(). If the client really opens, nothing in the NodeMCU documentation indicates that it will close itself; it may go offline.
Once connected, the client only knows that something is wrong when it sends a message and does not receive a response. It sounds like you are not calling :publish() much (which would otherwise let you know by returning false), so pinging may be best. If you expect to receive a message from the broker every n seconds, set a keepalive time slightly higher than that on the client.
Then, failure to get a response to those messages should trigger an event that you can respond to. That might be something like the following (not tested, may work better called outside the callback):
m:on("offline", function(client) m:close() end)

If a BLE can't force a disconnect, how can we authenticate a connection?

I believe I read that the peripheral side cannot terminate a connection?
terminate a connection CBPeripheralManager side
How then, can we authenticate a connection at the application level? We are making an iOS app connect to another iOS app, we only want them to connect to each other. After connection they exchange private-key-based challenge/response questions, and a failure should result in a refusal of the connection. This of course works fine on the central side, if it doesn't get the correct reply it closes the connection. But if the peripheral cant cancel the connection, then how do we prevent a different central from connecting, and staying connected to the peripheral?
When a central connects but does not authenticate correctly, do not respond to requests from it. Every CBATTRequest includes the requesting central, and updateValue(_for:onSubscribedCentrals:) lets you control which centrals you respond to.
If they're not authenticated. Don't talk to them. Or more correctly, send them .insufficientAuthentication to all their requests. If they are well behaved, they will disconnect. If they are badly behaved, there is nothing you can do about that (this is always true; even if you could disconnect them, they could still flood you with connection requests).
You cannot force them to disconnect, however. They may be communicating with another app, and you are not allowed to stop that. You can only refuse to talk to them yourself or send them errors.

Socket.io client fails to reconnect to server after an abrupt disconnection

I am using the socket.io NodeJs server library and the Swift client library. Majority of the time the client successfully reconnects to the server after a disconnection, however intermittently we are seeing abrupt disconnections and then the client is never able to reconnect.
In the server logs, I see the client sending a connection attempt at the defined re-try interval, however it just never successfully establishes the connection and then we get a ping timeout.
There is surprisingly very little support for Socket.io which makes this extremely difficult to solve.
I figured out a solution to our problem by forcing a new engine to be created in the client upon reconnections. When creating the SocketIOClient object, set the forceNew variable to true which allows the client to create a new engine and thus always successfully establishes the connection.
return SocketIOClient(socketURL: socketURL, config: [.forceNew(true)])

NSURLSession with background session configuration is not returning an error when there is no connection

When I set up NSURLSession/Alamofire.Manager with a background session configuration, if there is no internet connection, I'm expecting to receive the usual NSError "Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline.".
This happened regularly if I'm not using a background configuration, but if I do such configuration my callback/delegate method will never be called. It will eventually be called when I activate the wifi again.
I'd prefer to receive an error straight away. Am I missing something?
The reason that why the network failure in background session task does not return any error is:
In general an NSURLSession background session does not fail a task if
something goes wrong on the wire. Rather, it continues looking for a
good time to run the request and retries at that time. This continues
until the resource timeout expires (that is, the value in the
timeoutIntervalForResource property in the NSURLSessionConfiguration
object you use to create the session). The current default for that
value is one week!
I found the above answer at developer forum.
More details which might help in the background session:
Another benefit is that in a background session, we monitor the
network and power environment for you. This means that we cover things
like network reachability and connectivity for you, so you don't have
to use the reachability APIs at all. We won't attempt to establish a
connection until we know that the server is reachable. And similarly,
if the user is performing a download and steps out of Wi-Fi, normally
that task would then fail with a transmission error. But, in a
background session, we'll actually recover from that automatically and
retry it and resume where we left off if the download is resumable.
And you won't hear about that error.
Source: WWDC 2014
The API doesn't tell you that the network is not present, because that would be an error, indicating that the connection will never finish. In reality, it will, assuming the network eventually comes back.
If you need to receive the error for some reason, don't use a background session.
Alternatively, if you just want to know whether the network is up or not for some sort of UI hint, use the reachability API. With that said, don't refuse to start the request based on failed reachability, because reachability lies.

Check Worklight Client connection state

I'm working on a native iOS app that is using IBM Worklight server adapters, in my code every time I want to invoke a procedure I'm calling the WLClient().wlConnectWithDelegate(self) and then calling the adapter, is there a way that would let me check the connection status of the client before I invoke the adapter procedure?
There is no such API provided by the Worklight framework.
The idea behind the connect API is to establish a session between the client and server, negating the possibility for example of race condition (such as two adapter requests to the server, each getting its own session, potentially causing trouble), in addition to delivering data on headers that is no available in an adapter request compared to connect request.
I think that instead of making a connect request before invocation you can do it in an early stage in the app's lifecycle, as well as whenever the app returns to the foreground, to ensure that a session was established. This, coupled together wit an appropriate session timeout set in worklight.properties on the server-side.
More here: https://developer.ibm.com/mobilefirstplatform/documentation/getting-started-7-0/hello-world/connecting-to-the-mobilefirst-server/

Resources