I'm attempting to use YAWCam on my university network. I am using it as an mjpg streamer that another application behind another network needs to access. Unfortunately, there is no way to port forward on my university network. enter udp-hole punching. I thought this was fantastic when I learned of it, but quickly realized that, unless I could figure out how to actually modify this program (which is not open source) I would not be able to make UDP hole punching work conventionally.
My question is, is there a way to hole punch without changing the original program? possibly by sending packets from the same port yawcam uses to punch the hole, and then let regular requests refresh it? I'm a bit new to netcode so Im not entirely sure what the "correct" method is for this.
No it is not possible. Two different programs can't bind to same port. The purpose of port numbers is to identify which running application instance to route the traffic to. if two applications were to each bind two sockets to the same port number, that routing becomes impossible.
Related
The RFP for TFTP says that TID's in most circumstances:
should be randomly chosen, so that the probability that the same
number is chosen twice in immediate succession is very low.
The thing is, these "TID"s are also used as UDP port numbers. But a typical network interface cannot just be dedicated for TFTP use. Some ports are liable to be in use, and others should essentially be "reserved" for specific applications. I'm not even sure where a program could go to look up this information at runtime.
So how is a TFTP implementation supposed to deal with this?
Since the host selecting the TID/port is the one opening it and telling the other party which one it's opened, you can simply try to open the port; if it's already in use or otherwise unavailable, this will fail, and you can re-try with a different port. (Note that since UDP and TCP are difference protocols, a TCP application and a UDP application can both be using the "same" port, since they are not, in fact, the same at all!) Do this in a simple loop until you find a "good" one. (Probably best to define a maximum number of tries and simply fail the connection if that's met before a good port is found, as this could be a sign of other issues that prohibit this from working at all.)
Stick to the ephemeral port range to play nice with best practices, although note that different systems define different ranges for this purpose. You could pick the range suitable to your system, or simply try to use a port above the "well-known" port range (i.e. above 1024); this may not give you an "ephemeral port" per se for your system, but so long as you can open it it should work fine.
I have a weird problem. I have a successfully working C++ (boost asio) P2P application which works on most of the NAT. The problem is when I give the initial start port number as 1000 it checks if 1000 is free else increment by one and chooses a port and starts handshaking. But when I have 10000, 20000, or any other huge port number the hole punching doesn't work on port restricted cone NAT.
How is that possible? I am pretty sure it nothing to do with the code. and recently it doesn't work on one of my friends' full cone NAT as well, but it has worked in many other full cone NATs. What could be the reason? Is there something I am missing about how a NAT behaves?
In many NAT implementations, there are protection rules in place which prevent one host from tying up a large percentage of ports on the WAN interface, e.g. like described here.
Depending on the router, the NAT table entries have different lifetimes, and there are always limits on how many ports can be allocated to a single client (I've seen numbers from 128 to 4096).
So I think when you get to the point where you need to use high ports, the NAT table for your source IP address is already full (or almost full) with entries from old connections, or connections from other apps, so the router either decides to decline or can't fit the new NAT entry for your port.
However, to be sure, I would try to repeat that on a controlled environment collecting Wireshark dumps on both sides of the NAT and analyze the packets. If possible, it would also be helpful to enable router logs and peek into them.
I understand this is not a "magic bullet", but hope it somehow helps you.
Don't try to choose the port number yourself. The operating system can do this faster and better than your code can.
Bind your socket to port 0 and let the OS choose an available port number for you. You didn't specify what programming language, but it usually involves a call to getsockname() after the bind() call is made to discover what local port is going to be used. Java and .NET have equivalent APIs for doing the same thing.
Then follow all the other steps here:
https://stackoverflow.com/a/8524609/104458
Not sure if this'll help but have you tried having one instance of the client application starting at 1001 and the other starting at 1000, then both increment by 1.
While the 1000 will fail on client B, client A has already tried 1001 and so punched that hole, so hopefully it'll work, right? In theory, it sounds OK in my head.
I am trying to get a list of all IP's on a LAN network. The reason for this is I am writing an application that uses the STAR TSP100LAN receipt printer.
The process for obtaining the IP address of the printer is quite cumbersome for the end user. It involves turning the printer off, holding the paper feed button, turning the printer back on, waiting 15 seconds for the printer to obtain an IP address through DHCP and then finally spitting out a receipt with this information on it.
Seeing as the printer is not Bonjour enabled is it possible to get the IP address through other methods?
Any help is much appreciated! I hope this isn't a repeat question, but through my searching I can't seem to find a solution!
UPDATE: Ok after a bit of thinking I have come up with a pseudo-solution:
Determine the iPad's current IPAddress through NSHost.
Strip the last quadrant from the IPAddress
Using the stripped string as a prefix, iterate 1-255 for the last quadrant
Each iteration, attempt to open a port to the given address using the printer's sdk
If I get a valid response, I know that the IP is a printer
If not I exclude the IP from the available printers list.
So far this has been working, I set a timeout of 5 milleseconds for each port open attempt. But have found that this can return some null results despite there actually being a printer on the network with an IP Address assigned.
Perhaps if I get a null result the first time I should increase the timeout to 15 milleseconds for a second attempt at searching.
Your approach of polling the local /8 subnet is probably the best you can do. I can't find any API to get more detailed information about the network interface (i.e. subnet mask) in iOS. (Although using the subnet mask would be a more correct way to determine the range to iterate, if you could get it.)
As you've seen, 5ms is a pretty tight interval; In my experience, 15ms can STILL be pretty tight for a TCP connection over WiFi. As a next step, I would suggest parallelizing the polling of the range, and thereby enabling you to extend the interval you're willing to wait. The simplest way would probably be to use GCD. You could also start this polling process in the background before the user explicitly needs the printer, which might improve the user-perceived responsiveness of your app.
Alternately, you could use the CFSocket API to open all these connections (CFSocketCreate, CFSocketConnectToAddress, and friends) and get parallelism by servicing them all on the main thread with callbacks/the runloop. Then, as those callbacks come in, make a note of which addresses answer on the given port. Unless the printer isn't using TCP for some reason, this should be workable. Once you know which addresses answer on that port at all, you can iterate over that (hopefully much smaller) list connecting with the printer SDK itself. This approach will give you even more (and way more elegant) parallelism than spawning a huge number of GCD threads, but can be difficult to get your head around if you've not worked with runloops before.
Hope that helps.
You can quickly winnow the list down from 255 to a smaller number by pinging the broadcast address then looking into your arp cache.
Only works for hosts that respond to broadcast pings.
I have a question about the skype protocol.
Supposedly, according to wiki, the supernodes in Skype are used in UDP hole punching. The supernodes are nodes without firewalls/NATs.
My question is, how is this reliable? Isn't the vast majority of internet users behind NAT?
And, if I was to create a P2P application using this technique, what happens if there are no peers without firewalls? I don't understand how you can launch an application that relies on that there will be some peers eventually without NAT
Thanks
I can't comment on Skype specifically, but I have some experience with this (http://wiki.squeak.org/squeak/5629). We called our supernodes "big friendly giants" or BFGs :).
The idea behind supernodes is that while you hope that they pop up in the network, giving new users more options for NAT hole punching, you provide, as p2p network operator, a minimal set yourselves (could be just one or two machines, they are just needed for initial hole punching, real traffic will get re-routed directly anyway). As far as I'm aware, Skype does that as well - they run a minimum set of supernodes themselves.
When Skype had issues earlier this year, a lot of people tried to reconnect and thus the supernodes got overloaded, resulting in a domino effect. Skype added supernodes, but the amount of people trying to reconnect at that time was so massive that it took quite a while before the network rebuilt itself. It's quite funny - we had that with the above project as well - that a P2P network can be extremely resilient until it gets pushed over some edge and the whole thing crumbles.
[disclaimer: I work for eBay, former owner of Skype, but this is all my personal opinion and based on public information]
Read the papers on libjingle with discussion about services like STUN. When both parties are behind NAT an external service is often required to relay through or assist in punching a hole open on one or other side.
http://code.google.com/apis/talk/libjingle/important_concepts.html
I'm trying to create an embedded outdoor display of bus arrival times at my university. I'd like the device to utilize my school's secured WiFi network to show arrival time updates determined from a server script I have running.
I was hoping to get some advice on the high-level operation of this thing -- would it be better for the display board to poll a hosted database via the WiFi network or should I have a script try to communicate with the board directly over 802.11? (Push or Pull?)
I was planning to use a Wifly or WIZnet ethernet board in combination with a wireless access hub. Mostly inspired by this project: http://www.circuitcellar.com/Wiznet/winners/001166.html Would anyone recommend something else over one of the WIZnet boards? I saw SPI/UART options and thought these boards could work with an AVR platform.
And out of curiosity -- if you were to 'cold start' this device (ie, request a bus arrival time by pushing the display's on button) you might expect it to take 10-20 seconds to get assigned an IP and successfully connect to the database, does that sound right?
I'd go pull. In fact, I'd have outdoor display make http or https requests of the server. That way the server could tell it how long to show a given set of data before polling for a new one using standard http page expiration.
I think pull would make it easier to have multiple displays, and to test your server as well. I've also got a gut feeling that this would make your display more secure. Someone would have to hack your server to hijack your display.
There's a very cool looking Arduino-targetted product called the WiShield. Seems super easy to use and he provides some source code. It uses SPI for host communication. If you're not interested in going the Arduino route, I'm sure the source code wouldn't be too hard to port to something like avr-gcc. Check it out, might save you some time and headaches for $55. Worth checking out anyway.