Click here to Skip to main content
15,883,921 members
Articles / Programming Languages / C++

Portmappings on UPnP-NAT(s) using C++, winsock2, xerces2.8 (Linux friendly code)

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
28 Apr 2009CPOL 34.9K   759   26   3
Portmappings on UPnP-NAT(s) using C++, winsock2, xerces2.8 (Linux friendly code)

Introduction  

This article introducing a portmapping method and some IGD's UPnP SOAP actions using C++ without the Microsoft's COM library for the UPnP. So sorry, you have to setup libraries and VC paths like an image[red square] below. This project using boost-cpplib and xerces (DOM parsing). But I couldn't upload libraries with my source code because of an upload timeout with large file size.

dirplace.png

I had just tested soap responses from UPnP-enabled routers. I had not tested the connections and data streams as points of this article.

Sorry for potential bugs and my poor English.

  • Multiple NICs and multiple routers are supported. But CASCADED NATs are not supported.

Background

I want to implement the portmapping without third party (UPnP) libraries and attempt to write platform independent code AS POSSIBLE.

Using the Code

C++
#include "stdafx.h"

#include "Manager/ApplicationManager.h"
#include "Manager/COMManager.h"

#include "Network/NetworkManager.h"
#include "Network/NetworkHelper.h"

#include "NATBreak/UPNPNATServiceTypes.h"
#include "NATBreak/IGDDiscoverProcess.h"
#include "NATBreak/UPNPNATHTTPClient.h"

using namespace std;
using namespace boost;

thread_group tg;

int _tmain(int argc, _TCHAR* argv[])
{
	ApplicationManager am;
	NetworkManager nm;

	try
	{	
		IGDDiscoverProcess discoverer( 500000 );

		tg.create_thread( ref( discoverer ) );
		tg.join_all();

		IGDDiscoverProcess::IGDControlInformations cinfos = 
			discoverer.GetAllIGDControlInformations();
		boost_foreach( IGDDiscoverProcess::ControlInfo info, cinfos )
		{
			if( info.has_problem )
			{
				cout << "has problem" << endl;
				continue;
			}

			if( info.service_type == UPNPSERVICE_LAYER3FORWARDING1 )
			{
				// Layer3Forwarding:1 srvice

				UPNPNATHTTPClient soap( info.ip, info.port );

				soap.GetDefaultConnectionService
				( info.control_url, info.service_type );
			}
			else if( info.service_type == UPNPSERVICE_WANIPCONNECTION1 )
			{
				// WANIPConnection service
				UPNPNATHTTPClient soap( info.ip, info.port );
				string ip;
				UPNPNATHTTPClient::SoapResult res = 
					soap.GetWANIPAddress( 
					ip, info.control_url, info.service_type 
					);
				cout << "WAN IP : " << ip << endl;

				UPNPNATHTTPClient::SoapResult soap_res;
				soap_res = soap.AddPortMapping( 
				    string("test"), 12345, 12345, string("UDP"), 
				    string("192.168.0.2"), // own nic's address 

                                         info.control_url, info.service_type 
					);
				if( UPNPNATHTTPClient::SoapSucceeded == soap_res )
				{
					cout << "portmapping succeeded." << endl;
				}

				soap_res = soap.DeletePortMapping(
					12345, string("UDP"), info.control_url, 
					info.service_type
					);
				if( UPNPNATHTTPClient::SoapSucceeded == soap_res )
				{
					cout << "delete portmapping succeeded." 
						<< endl;
				}
			}
			else if( info.service_type == 
				UPNPSERVICE_WANCOMMONINTERFACECONFIG1 )
			{
				// WANCommonInterafaceConfig:1 srvice

				UPNPNATHTTPClient soap( info.ip, info.port );

				string ip;
				soap.GetActiveConnection( 0,  
					info.service_type, info.control_url );
			}
		}
	} 
	catch( IGDDiscoverProcess::exception &e )
	{
		cout << e.what() << endl;
	}

	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
	return 0;
}	

Points of Interest

  • In case when multiple UPnP-enabled NATs are cascaded
  • IPv6 support

History

This is the first version. 

The sample code has been fixed. The fixed part seems "string("192.168.0.2"),". This address means an own nic's address to send a m-search message.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Japan Japan
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralExcellent article Pin
xComaWhitex1-Dec-10 21:33
xComaWhitex1-Dec-10 21:33 
Thank you for the excellent article. Because I need to implement UPnP in my application and it's just a pita to understand due to lack of decent ones out there explaining how to properly do UPnP.

But these are just a few things. It'd be nice if it used Boost::Asio to remove all the old low level connection, use boost::scoped_ptr instead of boost::shared_ptr. Also is there a way to put this under LGPL as CPOL is not compatible with GPL, so I cannot use it this code until it does, and I'd have to rewrite it to use with my api. Also, more documentation in the code would be nice to explain how it works under the hood.

But thank you for the code ^_^
QuestionHow to compile the code with Boost? Pin
Tage Lejon28-Apr-09 22:45
Tage Lejon28-Apr-09 22:45 
AnswerRe: How to compile the code with Boost? Pin
Yohei Murakami6-May-09 2:40
Yohei Murakami6-May-09 2:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.