We are working on an iOS application for which we need to learn how VoIP works on 2 devices/machines which are on same local network. When transferring files between 2 Skype users on same network, the file transfer is very fast. So there must be something different when 2 devices are connected which are on same network.
Maybe file sharing is different than VoIP and at least the VoIP part works the same way for users on same network or on different networks. But if its not the case then I would like to know whats the difference between connecting machines on same and different networks via Skype.
Generaly VoIP is based on 3 protocols. SIP, RTP and RTCP.
Try to read some articles about SIP signalisation or SIP messages flow. The two devices within the same network can communicate directly or via SIP proxy. Basically the app has to support at least:
REGISTER
INVITE
CANCEL
BYE
100 Trying
180 Ringing
200 OK
486 Busy here
and few others SIP messages and status codes. Your app has to be able to handle SDP messages where the codec is negotiated - choose some free and open codec such as G.711 or iLBC. Within the SDP header RTP and RTCP port are negotiated as well, try to read something about SDP as well.
As this standard model uses multiple ports, it may cause issues when NAT is implemented, but this is not your case as you are within the same LAN.
Regardin the speed of transfer - if you are within the same network you shall not experience any impairments while calling - voice is transmitted in very small packets (i.e. 273 bytes) sent every 20 ms. If you are on wired 100 Mbit or 1 Gbit network, this shall work flawlessly. When on Wi-Fi some impairments may occur as it is not that much reliable.
Further information can be found here:
http://www.ietf.org/rfc/rfc3261.txt
https://www.rfc-editor.org/rfc/rfc4566.html
http://www.ietf.org/rfc/rfc3550.txt
I hope I answered your question at least a bit, if you have any further questions regarding VoIP feel free to ask.
Related
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.
I want to develop an android app which uses push to talk or Voip to communicate between 2 mobile devices using a Wi-Fi connection without using a data or the internet.
Is it possible to develop this?
I am looking for a 'free' Wi-Fi Walkie Talkie but I don't know how to start doing it?
For a very simple, initial version, I'd do the following:
Assign a static IP address on each phone
Record the audio and packetise it into a UDP stream that you'll send to the remote IP address
Repackage again the UDP stream and play the audio.
Microphone ---> Samples ----> UDP (over WiFi) ----> Samples ----> Speaker.
There are plenty of enhancements that you can add over the time:
Device discovery
Signalling separate (SIP or custom messages via TCP or UDP to indicate when to start the audio transmission and negotiate the media channel that will be used).
Support for third party devices (SIP)
Use standard paketization using RTP and encode the audio using G711alaw/G711ulaw...
There are plenty options, but you should start by capturing the audio, and sending it over the network, even make packets of 2 seconds with the incurring delay, but that's a point to start. Then, you should lower the packet length to contain 20ms of audio to avoid delays in the transmission.
Hope this helps.
Looking to place calls using our Cisco SPA504G IP phones through Twilio. We have 4 phone lines/numbers with Twilio and we want to use them to place and receive calls on physical phones.
Edited Question:
I found an interesting post in here: https://ertw.com/blog/2013/11/05/using-an-ip-phone-with-twilio/
This where my steps in order to get the phone to ring but I could not hear voice :/
I just bought: http://www.amazon.com/Grandstream-GXP1620-Medium-Business-Device/dp/B00VUU8EZM
Connected phone to my router. I am port forwarding all traffic in the ranges from 10000-20000 to the phone. I am also port forwarding port 5060 to the phone.
Uploaded the following xml file:
<Response>
<Say>Testing</Say>
<Dial>
<Sip>
sip:line1#24.51.221.98
</Sip>
</Dial>
</Response>
that can be found at: http://antnam.com/voip.xml
I called my internet provider and now I have a static IP address so that 24.51.221.98 never changes.
I configured my twilio number (855) 804-0420 to execute a GET # http://antnam.com/voip.xml
When I call (855) 804-0420 I can hear the phone that is connected to my router (voip phone) ring!!! So good news I am able to call the phone I purchased on step 1!
Once I answer the call I am not able to listen to voice :/ . What could I be doing wrong?
In summary everything works great I am just not able to listen to anything. It is as if the call is on mute. Am I missing to open more ports?
It sounds like this may just be a NAT traversal problem; if it is please move or remove this question, as this would only be relevant if you were programming this client. There is a ton of info out there about this issue (for example here is an excellent article that comes up as the first result when I google "voip nat traversal"), but here's a quick summary:
Why NAT causes a problem for VoIP
Most VoIP protocols use a data stream on one port (e.g. 5060 in this case) to negotiate connection information that includes among other things a socket (IP address and port) to receive audio/RTP traffic; there are 2 things about this negotiation of a socket that might be unexpected:
It can be any IP address and port combination, not just one that is on the VoIP device itself. So you might have for instance a VoIP server that negotiates a socket on another host that is not part of the SIP dialog, and which might be behind a NAT
The negotation is done at the OSI Application Layer (Layer 7), so it is normally untouched by the NAT process, which operates at Layers 3 and 4
How to diagnose missing audio due to NAT
If you're able to get packet captures (ideally on both WAN and LAN ports, so you can see your VoIP device's traffic before and after NAT), you can see the problem in action: just look for the packets containing SDP payloads (e.g. if you're doing SIP on UDP 5060, just filter for that port and you will see INVITE requests and 200 OK responses that contain SDP payloads); drill down to the c (Connection Information) and m (Media Description) lines, which should look something like the following:
c=IN IP4 192.168.1.114
m=audio 6094 RTP/AVP 0 8 101
If you're seeing something like this going out your WAN port, it means your VoIP device is requesting to be sent audio on 192.168.1.114:6094; the IP address is a private address and cannot be routed over the internet; the port is just one I picked randomly, but the one you see needs to be open and forwarded to your device
How to fix it
There are various solutions to this problem, which all come down to rewriting the private IP address that your device is giving out into the public one that your device's traffic is being NAT'd out on, so that when the remote device parses the Connection Information line in the SDP, it has a valid, publicly routable IP address to send the audio traffic to, and a UDP port that is NAT'd to your device. Sometimes the VoIP device itself can handle the rewriting (e.g. you can either statically tell the device in its configuration what its public IP is, or it can discover it from a protocol like STUN), sometimes the rewriting is done by the firewall/router that is doing the NAT (there are various names for this, like SIP ALG or SIP Fixup).
Unfortunately due to the variations in NAT implementations across various routers and firewalls, no solution can be guaranteed to work 100% of the time; and if you have multiple devices behind the same firewall, having it do the rewriting will only work for one of them.
In your case:
You mention 2 different VoIP devices, a Cisco SPA504G, and a Grandstream GXP1620. The datasheets for both devices say they support STUN, so I'd start looking in its config for the STUN settings or anything else that references NAT traversal. Also, make sure that the ports you are forwarding to the device are the ones that it uses, this is usually just another item in the config, called something like "RTP base port" or "RTP range"
I would also ensure that you nat transveral enabled with stun using a public stun server such as stun.sipgate.net
Note: STUN operates on TCP and UDP port 3478.
This is required as the phone needs to send the external ip in the sip packets. Without stun it will send the internal ip and the far end sip device will attempt to send the data there.
If I want to make sure that a device receives a message, over the network, for an app used by sellers in a shop for example.
I heard push notifications are not 100% reliable, sometimes some of the notifications don't arrive, or not on time.
The app could be in a shop, where the staff communicate with one another, and there could be 10 devices connected. (ipad, iphones)
edit 1: I heard about sockets, is it the right direction to go?
EDIT 2:
I am not sure why a socket should be used, rather than a webserver for example, I found these 2 sentences (source raywenderlich) :
You can send connected clients data whenever you want, rather than requiring the clients to poll.
You can write socket servers without a dependency of a web server, and can write in the language of your choice : don't understand what the "dependency" is?
Does it also mean :
Sockets let 2 (or more) specific devices to connect one another in a private connection, compared to webservers where everybody could connect if there is no login/password?
EDIT 3 : Maybe a bluetooth solution with MultiPeerConnectivity would be better...
Sockets, and push notifications in general, are only as reliable as the network the user is connected to. If your looking to circumvent network reliability where a 100% success rate is guaranteed, in a Shop environment where users are in close proximity, you can look into GKSession as part of the GameKit.framework
Or you could look into Bonjour or client/service discovery protocols that makes the process of "knowing" peers in a network
I see you tagged Parse.com, again, the reliability of Push Notifications is highly dependent on the reachability, however, most issues that arise with Parse is dev-end related, not product related.
EDIT I forgot to mention MultiPeerConnectivity
If you use TCP sockets, you are guaranteed the message will be delivered, and very quickly too.
However, the application would have to be open (and most likely in the foreground) to receive the messages. You can always have the server wait till the client connects to send the message.
I would suggest using a combination of both TCP sockets and push notifications (for when the app is closed).
I am trying to build an app for iOS that can connect to computers running macOS or windows, and control a few stuff on those computers. Another application will be installed on those computers so that the app on iOS can connect to them. But at first I need to discover those computers in the network that has my app installed and running. What is a good way of doing that? I thought about using broadcasting, multicasting or bonjour. Are there any other options? Which one is best for my situation?
I am planning on doing two different applications for macOS and windows, one with objective c and other with c#, so the networking stuff should be available for both of those. Thanks in advance
The simplest option by far would be to use IP/UDP broadcast packets. The application on the computers (running whatever OS) can all sit there listening on a predefined UDP port (e.g. 9999), and when the iOS device wants to 'scan' the network, it will send out an IP/UDP broadcast packet with the destination port of 9999. Upon receiving the broadcast packet(s), the application on the computers can respond since it now knows the IP address of the iOS device, and you can take things from there.
The cleanest way to handle a computer leaving the network is for the application that is running on the computer to communicate this fact to the iOS device since it already knows the IP address of the iOS device. But if keeping a current list of computers is crucial, then some sort of a polling mechanism is unavoidable because the computers may crash for whatever reason without having the chance to send the bye-bye message.
Multicasting can be utilized as follows: computers periodically send IGMP joins for a predefined multicast group (e.g. 224.1.1.1), and iOS device sends the multicast UDP packet destined to 224.1.1.1 when it wants to 'scan' the network. The multicast UDP packet(s) will be received by the computers since they have already joined the multicast group of 224.1.1.1, and then the computers can start communicating with the iOS device now that the IP address is known. However, this seems overly complex, and does not really offer any advantages. The whole point of using multicast is to save bandwidth, but the amount of bandwidth saved will be minuscule. Unless you are going to send the same data in substantial quantities from the iOS device to all the computers, there is simply no reason to go down this path.
As for Bonjour, unfortunately I am unable to comment as I have no experience with it, but I would still vote for simple broadcasting to keep things platform independent... well, at least on the computers side. :)