How to Find Latency of Other Connected Device via TCP Socket in IOS - ios

is sending a message to the device which is connected via TCP Socket and calculate the time it takes to reply is the right approach?

The most common implementation for checking networking latency is based on ICMP packages and is called ping.
There is a nice and easy sample available from Apple.
Please note that even though the sample is provided for OSX, it should build and work fine on iOS as well.
Here are some additions I just found: splinter.com.au/how-to-ping-a-server-in-objective-c-iphone
I would go with ping as that way you would not have to build the "echoing" part yourself, that part is done by the remote system/network-stack.

Related

What triggers the "would like to find and connect to devices on your local network" permission notification on iOS 14?

What actual method calls, excluding Bonjour, triggers the "would like to find and connect to devices on your local network" permission notification on iOS 14?
This is the screen shot from the WWDC session on this new permission. Which is only somewhat helpful as an overview. I'm more interested in figuring out what all method calls trigger this.
If you're using react native with a debug configuration, then you are including all the code responsible for communicating with your dev machine so you can probably ignore this message.
However it's best to check you have no other libs that require access too. To do this just build a Release version and see if the message persists.
In a nutshell, Bonjour. Its use is no longer "transparent". See https://developer.apple.com/videos/play/wwdc2020/10110/ for more information:
If your app interacts with devices using Bonjour or other local networking protocols, you must add support for local network privacy permissions in iOS 14.
Even an existing app is subject to this rule; the first attempt to use Bonjour triggers the authorization alert.
Apple (Eskimo on the Dev Forums) released a FAQ providing more details around this alert:
https://developer.apple.com/forums/thread/663858
Particularly, providing more info as to what triggers this alert is FAQ-2:
https://developer.apple.com/forums/thread/663874
What operations require local network access?
The general rule is that outgoing traffic to a local network address
requires that the user grant your app local network access. Common
scenarios include:
Making an outgoing TCP connection — yes
Listening for and accepting incoming TCP connections — no
Sending a UDP unicast — yes
Sending a UDP multicast — yes
Sending a UDP broadcast — yes
Receiving an incoming UDP unicast — no
Receiving an incoming UDP multicast — yes
Receiving an incoming UDP broadcast — yes
These TCP and UDP checks are done at the lowest levels of the system
and thus apply to all networking APIs. This includes Network
framework, BSD Sockets, NSStream, NSURLSession and WKWebView, and any
other protocols that you layer on top of those.
IMPORTANT Receiving an incoming UDP multicast or broadcast does not
currently require local network access but, because we hope to change
that in a future update, our advice right now is that you write your
code as if did (r. 69792887, 70017649).
Resolving link-local DNS names (those ending with local, per RFC 6762)
requires local network access. Again, this check applies to a wide
variety of APIs including <dns_sd.h>, <net_db.h>, Network framework,
NSStream, and NSURLSession.
Finally, all Bonjour operations require local network access:
Registering a service with Bonjour — yes
Browsing for Bonjour services — yes
Resolving a Bonjour service — yes
Again, these checks apply to all APIs that use Bonjour, including
<dns_sd.h>, Network framework, NSNetService, and Multipeer
Connectivity.
Note You must declare the Bonjour service types you use in your
Info.plist. See How do I map my Multipeer Connectivity service type to
an entry in the Bonjour services property? for details.
Bonjour-based services where you don’t see any details of the network
do not require local network access. These include:
AirPlay — no
Printing via UIKit — no
One of my apps was triggering this prompt unexpectedly in our internet multiplayer mode. We use RakNet for our networking (which is a C++ lib that uses BSD sockets to send/receive UDP) and I was able to track the problem to the RNS2_Berkley::BindShared function here.
After creating a UDP socket, RakNet tests health/validity of the socket by having it send a little test packet to itself. iOS 14 was flagging this send-to-self behaviour as communication on the local network. I'm not sure if this send-to-self behaviour is a common pattern in socket programming, or a particular quirk of RakNet. Frustratingly, the OS prompt didn't actually appear until later when the socket was used for real which made the issue very hard to track.
I think that this is a false-positive from the OS and raised it with Apple (FB8802121). I won't be holding my breath though so I've just disabled that RakNet behaviour for iOS and am hoping that it wasn't too important.
Edit: To more directly answer the original question: sendto is a method call that can trigger this prompt.
I get rejected from apple app review for this alert. I'm using GCDWebServer which creates an embedded http server in my app.
I think I should provide a message in info.plist to tell user what my app want to do. Before I didn't set the text string in it.
And I would like to update if this will pass the app review.
<key>NSLocalNetworkUsageDescription</key>
<string>xxx uses the local network to connect with devices around you.</string>
Regarding iOS 14: permission request: would like to find and connect to devices on your local network and after numerous deploys to my physical device, I have figured out what causes this in my case.
I have a Xamarin.Forms app which
calls localhost:xxxx to do some local logging while I develop
I use a product thats called LiveSharp that does local hot reloading for XAML AND C# code changes.
So Livesharp actually communicates with a server on my localhost as well.
After disabling both of these and a fresh clean install on my physical device, the permission request has GONE .. Yay
Note: I had to completely remove LiveSharp nuget packages from my project.
Also I tried to re-enable my localhost logging, and for some reason the permission request does not appear.. :headscratch
So: remove any localhost communication that happens in your app. Or at least put an if statement around it allowing it if set to true in appsettings
I also have a Xamarin app and I used the package LiveXaml. After removing it the message was gone.

Framework for communicating between iOS and MacOS

I'm looking to build a pair of apps that work in a similar way to iTunes and the Remote app for iOS... Is there a framework for connecting iOS and MacOS over wifi?
Bluetooth is something I'd like to avoid and there's no need for a web service, I'm just looking to control my Mac app remotely from the phone.
Thanks in advance.
Id say the most ideal way to accomplish this is via the Bonjour protocol.
Here is a great article on the subject, http://mobileorchard.com/tutorial-networking-and-bonjour-on-iphone/.
Good thing with using Bonjour in iOS is it also works via Bluetooth.
Hope this helps !
here is an example project which exchange the data between iphone and iMAC with WiFi connectivity.
https://github.com/boobalaninfo/Bonjour-iOS-MAC-Apps
Use bonjour to search for devices. Then use CocoaAsyncSocket to send and receive data. It works like a charm.
Little info about AsyncSock:
GCDAsyncSocket and AsyncSocket are TCP/IP socket networking libraries.
Here are the key features available in both:
Native objective-c, fully self-contained in one class. No need to muck
around with sockets or streams. This class handles everything for you.
Full delegate support Errors, connections, read completions, write
completions, progress, and disconnections all result in a call to your
delegate method.
Queued non-blocking reads and writes, with optional timeouts. You tell
it what to read or write, and it handles everything for you. Queueing,
buffering, and searching for termination sequences within the stream -
all handled for you automatically.
Automatic socket acceptance. Spin up a server socket, tell it to
accept connections, and it will call you with new instances of itself
for each connection.
Support for TCP streams over IPv4 and IPv6. Automatically connect to
IPv4 or IPv6 hosts. Automatically accept incoming connections over
both IPv4 and IPv6 with a single instance of this class. No more
worrying about multiple sockets.
Support for TLS / SSL Secure your socket with ease using just a single
method call. Available for both client and server sockets.

Sometimes socket dies when switching wifi to 3g iOS posix sockets

I've searched the web extensively but haven't found a good answer to this.
Im writing a socket based application in C++ using posix sockets on iOS/Android.
When switching from wifi->3g, SOMETIMES the socket goes dead without giving any errors when reading/writing.
I can use the reachability API on iOS (and similar on android) to detect when the network switches.
I am destroying/recreating the socket when this occurs. The problem is if the socket is alive, the server will receive the signal when I close the socket. If the server receives the close signal, it will assume the client disconnected intentionally and notify others about this, which is not what I want. If the socket is dead, the server doesn't receive this signal and everything is OK.
How do other people handle this scenario? I really don't want to use a timeout to detect this.
Why does it only sometimes die too? And how can I tell the socket is actually dead?
Just to close this issue, this is the approach I'm taking.
When switching networks, I'm sending a ping-and-reconnect packet to the server, AND creating a new socket.
Which ever responds first, I close the other connection.
Required a bit of server side changes to handle this correctly too

How to make iOS believe there is Internet Connectivity

I am working on a web application for iOS that is going to be accesed from a local webserver in a network that has NO internet connectivity at all.
My problem is that everytime an iOS device is locked, it disconnects from the WiFi network, so when the device is unlocked again, it has to reconnect. Part of that reconnection process is determining if there is Internet connection (which there isn't). Until the process is not finished iOS does not allow any DNS resolution (so if I write http://10.0.0.1 it will go there, but not if I request http://something.local.com).
Since we control that network, we want to know how to does iOS verifies Internet connectivity so that we can fake the responses it expects.
I don't know if it's possible to resolve DNS without an internet connection on iOS, but if that's the case, that would be a way better solution since you don't need to mess with your router settings. Use my solution only if it really isn't possible with only code.
I'll suggest you to follow this guide: http://blog.jerodsanto.net/2009/06/sniff-your-iphones-network-traffic to check which actions your iPhone executes to detect an internet connection.
Using this information you could forward the is-there-internet-requests on your router to a local server which fakes the there-is-internet-responses.
This assumes Apple really uses an external server to detect this, which I'm not sure about. But it wouldn't hurt to give it a try!
Have you looked at the Reachability Class? You don't have to use the reachabilityForInternetConnection method, which checks if a default route is available. You can use the reachabilityWithAddress: method and check if your server is reachable.

Best way to find is my custom ethernet device is online and what IP it has got for iOS?

Ideas:
1. Pinging all my subnet ( using simple ping etc )
2. Sending GET to all IP in my subnet? ( may be too slow) waiting for 200 or 404 reply.
Thanx
Can you program your ethernet device to respond to Bonjour (mDNS) requests? That's the preferred discovery mechanism in the OSX/iOS ecosystem. avahi is an open-source mDNS daemon you might be able to run if your device runs a UNIX-like OS. You might also be able to find or write an embeddable mDNS server that you could integrate into your server if you're not running an OS as such.
Otherwise, I'd probably go with a custom broadcast UDP packet that the device will respond to. (which is basically what Bonjour/mDNS does, but less general) To send a broadcast UDP packet, open a UDP (datagram) socket and send a packet to the local subnet's broadcast IP. Make the packet contents suitably unique, and get your device to respond, e.g. using an HMAC, to avoid picking up any other devices or daemons which coincidentally answer on the same port.
This is a pure IP networking question. What you want to do is to send a TCP/IP broadcast message to the network and have you custom device respond to it. See TCP/IP Guide for some basic details.

Resources