Sunday, July 13, 2008

UPnP and NAT-PMP PortMapper for Windows

If you're looking to add UPnP support and/or NAT-PMP support to your app, Cocoa developers need look no further than TCMPortMapper. This is a wrapper around the excellent MiniUPnP project. But what if you're a Windows .Net developer?

We scoured the web for such a library and found little help. There were expensive commercial solutions, bits of concept code found on forums, and an especially complicated API from Microsoft. And none of these even seemed to know about NAT-PMP!

So we took another look at the MiniUPnP project. After all, this is what TCMPortMapper uses. And we discovered it's mission statement is exactly what we're looking for:
An open source library with a commercial friendly license, providing the simplest library possible, with the smallest footprint and no dependencies to other libraries such as XML parsers or HTTP implementations.

Sounds perfect! And it's in pure ANSI C. Does this mean it works on Windows???

Yes and no. The miniupnp part of the library was Windows compatible. But you had to compile it using MinGW. Basically, the MinGW project provides Windows implementations of common unix libraries so that many unix projects can be compiled into a single windows executable. So we toiled on that for a bit, and finally figured out how to compile the library into an exe and/or dll. Next was the libnatpmp part of the library. This wasn't Windows compatible yet, so we had to write a bit of code. (By the way, traversing the windows registry in pure C is a lot of fun. You should try it sometime when you're looking to ruin your day.) So now the official libnatpmp code is Windows compatible, and comes with instructions on compiling for Windows. I believe the miniupnpc download comes with the actual dll now too!

And with that out of the way, we could port TCMPortMapper to a .Net library. Which meant all kinds of fun P/Invoking and marshaling data back and forth from managed to unmanaged code. And now, a few weeks later, we're finally done. (Thank God)

So today, we're releasing the DotNetPortMapper. It retains pretty much the same API as it's Mac counter-part. And here's pretty much all you have to do to use it:

using TCMPortMapper;

private void Form1_Load()
{
PortMapper.SharedInstance.Start();
PortMapping pm = new PortMapping(localPort, publicPort,
PortMappingTransportProtocol.TCP);
PortMapper.SharedInstance.AddPortMapping(pm);
}
private void Form1_FormClosing()
{
PortMapper.SharedInstance.StopBlocking();
}


And that's it. If UPnP or NAT-PMP is available on your local network, the port mapping will be added, and also properly removed when your app terminates.

Also included in the project is a sample "Port Map" application. This app shows how to add/remove port mappings, and how to do other more advanced tasks such as obtaining your external IP address, and learning the router manufacturer. A picture is a thousand words:





DotNetPortMapper Google Code Page

Browse PortMapper Source Code

Download Project (using subversion)

If you're unfamiliar with subversion, it's really easy to use. (And as a developer it's very important to learn and use source control systems.) Windows users should have a look at Tortoise SVN. Mac users may want to look at Versions.

10 comments:

Anonymous said...

Hi guys,

AWESOME contribution! I tried out your Port Mapper app, and also tried the source code you referenced in this blog entry, but wasn't able to get it working.

I'm getting a failure in the line where it tries to read the URL and parse out the IGD data structure from it.

I tried pasting the XML but the comment box isn't letting me do so.

My email is jahanzeb [@t] gmail.com -- I'd be happy to collaborate with you guys on this. Please email me, and I can send you the XML output.

Any possibility of releasing the code that makes up the dll's, and even better, any possibility of putting it in a form that's debuggable using Visual Studio?

DJ said...

Hello! I want to use your software to bypass the NAT used by my router, because isn't capable of port forwarding.

When I use the sample app provided however, it only displays "searching for router". Do you have any ideas for troubleshooting that I can do to make the sample app work as described above?(I'm no dev so i don't know so much technical stuff).

If not, are there any other programs out there that do NAT-PMP for Windows? thanks in advance

Robbie Hanson said...

Hi DJ,

The code is designed to interact with routers that support either UPnP or NAT-PMP. If the router doesn't support either of these protocols (or doesn't have that support turned on) then one is out of luck. The only other option would be NAT traversal...

DJ said...

Hello Robbie!
Thanks for your reply!
My router is a Speedtouch 585(i), which does support UPNP, but not NAT-PMP.

Yet, it is not able to find my router. I don't know why it won't work, i've turned off both my router firewall(which doesnt even block outgoing connections) and my soft firewall of my PC, to no avail.

Do you have any ideas on what may be causing this? Or do you think it's simply due to lack of compatibility with my router?

Thanks in advance.

Robbie Hanson said...

There are many routers out there that support UPnP, but most of them have UPnP disabled by default. Have you checked the router settings to verify that UPnP is turned on?

Anonymous said...

Hello,
I've been looking into using your tcmportmapper library. I was curious as to what language you wrote it in. I see that the actual project is written in C#, is the library also written in C#?

I have a project in C++ that I was looking to use this with possibly.

Thank you!

Robbie Hanson said...

The project is written in C#/.Net, but the miniupnp library files that it uses are written in C and compiled into a dll. The project uses pinvoke and marshaling to communicate with the dll files from .Net.

Anonymous said...

Ok, thank you for answering. For the tcmportmapper.dll, are there any header files for that? or is that a C# dll?

William Lee said...

on windows 7 it says "PortMap has stopped working. Windows is trying to find a solution to this problem" then it says i have to close it! Please email me at kirimlee1@gmail.com

Alexander Kent said...

Nice one.
Do you have a working "mingw32make.bat" ? Having a hard time with MinGW / Makefile.mingw.... how did you compile the DLL under windows?