So I have been trying to create two GCDAsyncSocket's in my project, one (socket) that uploads a file to my server and the other (listenSocket) waits for another process from the server to communicate with it. In my ViewController I have initialized them in viewDidLoad method and setup delegate to self for both sockets.
socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
listenSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
I then made the listenSocket start listening by
NSError *err = nil;
if (![listenSocket acceptOnPort:19920 error:&err]) {
NSLog(#"listenSocket failed to accept: %#", err);
}
I then made socket to connect to remote server and start uploading files.
The problem is that socket works fine and can upload and also read response from my server, but it seems that I can't access the accepting listenSocket by any way. Not by the other process on server, nor by using telnet or by typing the ip address and port number into browser. Why is this and how do I fix it?
Edit:
Here's what I am doing with my app:
I am working on an app that programs for Arduino on iPhone. Due to App Store policy the compiling and uploading process has to be on server, so I'm using socket to upload the code to server to get it compiled. In order to upload the compiled binaries to Arduino, I have to run avrdude which fortunately would accept an ip + port address instead of a usb connection as target. avrdude is implemented so that it connects to the address as a client, so I have to open a listening socket on my app.
I imagine your issue relates to your device not having a routable IP address from the outside world. I have assumed here that you are not testing on a local network with your server and phone both using this network via wifi/cable.
When you are on your device using a mobile network, it is assigned an IP address from the mobile operator. This address is more than likely an address which is part of their internal mobile network. When you connect outside of the mobile network to a server, the address the server sees for your device is not the address you see on the device. The addresses are mapped in transit as your IP packet passes through the various gateways while on its way to the server. Thus when you server sees a connection requested on a listen socket, it has a reply address which when used allows the reply to traverse back to your device.
A similar issue occurs when your device is on WiFi behind a NAT router. Connections made outgoing are seen by the router and it changes the from IP address to be that of the router. Since it sees the start of the conversation, it know where return packets with a given port and sequencing should be routed. However if somebody wants to connect to your device from outside, you have to have set up port forwarding on the router for a known port telling it where to send connection packets.
So applying this to your situation:
Outgoing Works (Why):
Your outgoing socket works, because you are connecting to an externally visible IP. When you connect, the network knows exactly where the packet has to go and the reply address is provided in the packet by the network.
Incoming Does Not Work (Why):
Your listen socket will not be working because the address you are sending to does not exist on the open internet. To make a connection from the server or anywhere else to your device you would need an IP which has a routing mapped through to your device. If the device is on a mobile network, you need an external IP for the mobile network which maps to your device. If the device was behind a NAT router, you would need port forwarding set up.
Solution:
Unfortunately, there is no easy solution as your need an IP address for your device in the outside world. Much depends on your use case which you have not mentioned. You either need an external IP which is reliable or you need to use an intermediate server to handle messaging or you need to change your approach and have the device poll every so often for information.
This is a problem which has existed for a long time and is why peer to peer companies have smart algoithms for connecting peer to peer services which use clever techniques like hole punching to connect devices.
IMHO I would move to a model where your device always initiates the connection if you can.
Related
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.
iam trying to test my application to public network so i will use my own ip as server , i already did port forward in my router settings, " my goal is reach this application to computers out side my network " but i only can receive data i cannot send from my main ip to other computer ,, i have disabled my firewall also the other pc firewall is this problem of my router ? or my network ?
i tried to disable router firewall but still same problem is there other things i have to check ? also i set my indtCP server binding to 0.0.0.0 to reach all network.
You should be able to send, but only after the client connects to your server.
When a client connects you should handle OnConnect event of your TIdTCPServer component. AThread parameter represent your client. You can respond to it by, for example:
AThread.Connection.Write ('Hi!');
You can disconnect the client by:
AThread.Connection.Disconnect;
Of course, many clients can be connected at the same time. In this case, you should keep track on all (dis)connected clients.
If I have an iOS client and an embedded device that I want to communicate between the two with a WiFi connection using UDP, do I need to write a server (python or something) to facilitate the connection? I am trying to look online but there are a lot of ambigious articles.
Thanks
You'll have to write a server application for the device (iOS or embedded) that will be listening for data.
However, for a simple, single-client UDP connection, your server is basically just a UDP socket, which you bind to the port you want to use - and then start listening for data on. You don't need any connection-handling as UDP is connectionless.
On your client, you just send data to the IP and port of your server, and that's it.
I've done this myself, connecting my iPod Touch to a small ITX computer (running WinXP), to control a small mobile robot over WiFi.
I'm building an application that will run in a museum with a local area wifi network without internet access, for some strange reason I'm not able to fully "join" this network with an iOS device. Enabling internet access on this network solves the problem...
The network should provide only a web server and a DNS server, the access point has a DHCP server, android devices can connect to the network without problems.
When I try to join the network with the device it remains in a "spinning wheel" status, the DHCP server log on the debian server says it has assigned an address to the iOS device, and if I check for the wifi address with an application (like iSys o SBSettings) I see the WIFI DHCP assigned address.
But when my app (or safari) tries to connect to the web server the request is routed through the 3G connection and not completed.
In my app I'm using the standard "Reachability" framework from Apple to check the reachability of a provided host name through the wifi connection and I get 0 on the SCNetworkReachabilityFlags mask....
I'm quite sure the problem is due to the fact iOS (5.1 in my case) tries to check the reachability for some "standard" host in the network, before routing traffic through the WIFI connection.
Anyone knows what an iOS device do to "validate" a WIFI network? I can add hostnames or simple dummy services to the server machine if this can help me connect the device to a LOCAL-only network :)
It seems that iOS doesn't like to join networks without a gateway, also if the network is local you have to setup a correct gateway address.
Setting the gateway as the server itself did the trick and the device started to route TCP/IP over my local area wifi network.
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.