Help with UPnP? (code)

Started by
3 comments, last by hplus0603 13 years, 7 months ago
Hi, I need a little help with uPnP if anyone can spare a minute.

I wanted to learn socket programming, so I made a nice little web server that uses IO completion ports and all that good stuff. When I forward the port manually from within the my router's settings, the server runs fine. I recently tried to get it to work with uPnP, but had no luck.

I tried connecting to the server from outside my home network, but couldn't get a response.

I checked that:

1) uPnP is enabled in the router's settings
2) I am not receiving any errors from my code


This is the code for the wrapper that I made:

mappedport.h
#ifndef INC_MAPPEDPORT_H#define INC_MAPPEDPORT_H#pragma comment (lib, "ws2_32.lib")#include <winsock2.h>#include <ws2tcpip.h>#include <Natupnp.h>#include <Windows.h>class MappedPort{private:	HRESULT hr;	wchar_t protocol_[4];	long lport_;	bool initialized_;	bool mapped_;	IUPnPNAT *uPnP;	IStaticPortMapping *spmOut;	IStaticPortMappingCollection *spmCol;	bool Initialize();public:	MappedPort();	MappedPort(long lPort, wchar_t *protocol /* "TCP" or "UDP" */, wchar_t *description);	~MappedPort();	bool Map(long lPort, wchar_t *protocol /* "TCP" or "UDP" */, wchar_t *description);	bool Unmap();	bool IsMapped();};#endif /* INC_MAPPEDPORT_H */


mappedport.cpp
#include "mappedport.h"MappedPort::MappedPort(){	Initialize();}MappedPort::MappedPort(long lPort, wchar_t *protocol, wchar_t *description){	if(Initialize())		mapped_ = Map(lPort, protocol, description);}bool MappedPort::Initialize(){	lport_ = 0;	mapped_ = false;	initialized_ = false;	hr = 0;	uPnP = NULL;	spmOut = NULL;	spmCol = NULL;	if(CoInitialize(NULL) == S_OK)	{		hr = CoCreateInstance(__uuidof(UPnPNAT), NULL, CLSCTX_ALL, __uuidof(IUPnPNAT), (void **)&uPnP);		if(hr == S_OK && uPnP != NULL)		{			hr = uPnP->get_StaticPortMappingCollection(&spmCol);			if(hr == S_OK && spmCol != NULL)			{				initialized_  = true;			}		}	}	return initialized_;}MappedPort::~MappedPort(){	if(mapped_)		this->Unmap();		if(uPnP) uPnP->Release();	if(spmCol) spmCol->Release();	if(spmOut) spmOut->Release();	if(initialized_)		CoUninitialize();}bool MappedPort::Map(long lPort, wchar_t *protocol, wchar_t *description){	WSADATA wsaData;	char hostname[256];	PHOSTENT hostinfo;	wchar_t ip[16];	lport_ = lPort;	wcscpy_s(protocol_, 4, protocol);	if((initialized_ == true) && (mapped_ == false))	{		spmCol->Remove(lport_, protocol_);		if(WSAStartup(MAKEWORD(2,2), &wsaData) == 0)		{			if(gethostname(hostname, sizeof(hostname)) == 0)			{				hostinfo = gethostbyname(hostname);				if(hostinfo != NULL)				{						if(InetNtopW(AF_INET, (struct in_addr*)*hostinfo->h_addr_list, ip, sizeof(ip)) != NULL)					{						if(spmCol->Add(lPort, protocol, lPort, ip, TRUE, description, &spmOut) == S_OK)						{							mapped_ = true;						}					}				}			}			WSACleanup();		}	}	return mapped_;}bool MappedPort::Unmap(){	return (spmCol->Remove(lport_, protocol_) == S_OK);}bool MappedPort::IsMapped(){	return mapped_;}


If someone could point out any obvious errors that I am making here, it would be greatly appreciated.

bonus: if you can fix it, you can keep it =D

thanks

[Edited by - CPPNick on August 30, 2010 8:46:13 AM]
Advertisement
I'm really surprised I didn't get any answers for this. Anyways, it works now. I edited the code above to reflect the newest, working code, for uPnP (automatic port forwarding).
The reason is probably that most people think UPnP is a bad idea, for two reasons:

1) It removes one of the securities of a firewall -- the firewall administrator is no longer in control of traffic.

2) It's fundamentally broken -- if two users want to host the same port, they can't. A real game hosting system/broker would allocate different ports to different users behind the same firewall.
enum Bool { True, False, FileNotFound };
Do you know how this problem will be handled in the future then?
Does the IPv6 protocol address this somehow?

I imagine that all it would take to overcome this would be to update the TCP/IP packet header to also contain a private network IP.

anyways, imo, if people download illegally cracked software, and get a trojan, that should be their problem...and as far as operating systems go, I would rather click "allow" for each incoming or outgoing connection then have to deal with virus scanners or firewalls.. people take computers for granted way to easily... I am not going to try and start a flame war here, but I hope that the new EHF fees they are imposing on computer products in Canada are just the beginning. There should be laws that protect people's rights to use their technology. If I can get a ticket for speeding, why not for spamming ? :)
[quote[Do you know how this problem will be handled in the future then?

It's already handled just fine, through NAT punch-through and public matchmaking services, and putting "real" servers in data centers with public IPs (or behind reverse NAT). The idea that consumers can put useful "servers" in their closet for the greater Internet to use without help from some more central dictionary isn't all that viable IMO.

Quote:Does the IPv6 protocol address this somehow?


With IPv6, there's enough IP addresses so that NAT won't be needed, so firewalling becomes a responsibility of the host, not the router/gateway.
Of course, they designed the IPv6 address space totally without any regard for mobile IPs, and mobile IP is growing at 10x the rate of stationary IP, so whether that will actually ever solve anything is a different question :-)

AFAICT, IPv4 with NAT and central match-makers are here to stay for some time.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement