← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2421: port mapping tweaks

 

------------------------------------------------------------
revno: 2421
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Sat 2011-02-12 16:11:02 +0100
message:
  port mapping tweaks
removed:
  natpmp/natpmpc.c
modified:
  dcpp/Mapper.h
  dcpp/MappingManager.cpp
  win32/Mapper_MiniUPnPc.cpp
  win32/Mapper_NATPMP.cpp
  win32/Mapper_NATPMP.h
  win32/Mapper_WinUPnP.cpp


--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk

Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'dcpp/Mapper.h'
--- dcpp/Mapper.h	2011-02-11 23:08:25 +0000
+++ dcpp/Mapper.h	2011-02-12 15:11:02 +0000
@@ -25,8 +25,8 @@
 class Mapper : boost::noncopyable
 {
 public:
-	Mapper() { printf("mapper constructor\n"); }
-	virtual ~Mapper() { printf("mapper destructor\n"); }
+	Mapper() { }
+	virtual ~Mapper() { }
 
 	enum Protocol {
 		PROTOCOL_TCP,

=== modified file 'dcpp/MappingManager.cpp'
--- dcpp/MappingManager.cpp	2011-02-11 23:08:25 +0000
+++ dcpp/MappingManager.cpp	2011-02-12 15:11:02 +0000
@@ -73,6 +73,13 @@
 	if(renewal) {
 		Mapper& mapper = mappers[working];
 
+		ScopedFunctor([&mapper] { mapper.uninit(); });
+		if(!mapper.init()) {
+			// can't renew; try again later.
+			renewal = GET_TICK() + std::max(mapper.renewal(), 10u) * 60 * 1000;
+			return 0;
+		}
+
 		auto addRule = [this, &mapper](const unsigned short port, Mapper::Protocol protocol, const string& description) {
 			// just launch renewal requests - don't bother with possible failures.
 			if(port) {
@@ -87,7 +94,7 @@
 
 		auto minutes = mapper.renewal();
 		if(minutes) {
-			renewal = GET_TICK() + minutes * 60 * 1000;
+			renewal = GET_TICK() + std::max(minutes, 10u) * 60 * 1000;
 		} else {
 			TimerManager::getInstance()->removeListener(this);
 		}
@@ -98,15 +105,15 @@
 	for(auto i = mappers.begin(); i != mappers.end(); ++i) {
 		Mapper& mapper = *i;
 
+		ScopedFunctor([&mapper] { mapper.uninit(); });
+
+		if(!mapper.init()) {
+			log(str(F_("Failed to initalize the %1% interface") % mapper.getName()));
+			continue;
+		}
+
 		mapper.close();
 
-		ScopedFunctor([&mapper] { mapper.uninit(); });
-
-		if(!mapper.init()) {
-			log(str(F_("Failed to initalize the %1% interface") % mapper.getName()));
-			continue;
-		}
-
 		auto addRule = [this, &mapper](const unsigned short port, Mapper::Protocol protocol, const string& description) -> bool {
 			if(port && !mapper.open(port, protocol, boost::str(F_("%1% %2% port (%3% %4%)") %
 				APPNAME % description % port % Mapper::protocols[protocol])))
@@ -142,7 +149,7 @@
 
 		auto minutes = mapper.renewal();
 		if(minutes) {
-			renewal = GET_TICK() + minutes * 60 * 1000;
+			renewal = GET_TICK() + std::max(minutes, 10u) * 60 * 1000;
 			working = i - mappers.begin();
 			TimerManager::getInstance()->addListener(this);
 		}
@@ -159,7 +166,12 @@
 
 void MappingManager::close(Mapper& mapper) {
 	if(mapper.hasRules()) {
-		log(mapper.close() ?
+		bool ret = mapper.init();
+		if(ret) {
+			ret = mapper.close();
+			mapper.uninit();
+		}
+		log(ret ?
 			str(F_("Successfully removed port mappings from the %1% device with the %2% interface") % deviceString(mapper) % mapper.getName()) :
 			str(F_("Failed to remove port mappings from the %1% device with the %2% interface") % deviceString(mapper) % mapper.getName()));
 	}
@@ -177,7 +189,7 @@
 }
 
 void MappingManager::on(TimerManagerListener::Minute, uint64_t tick) throw() {
-	if(tick >= renewal)
+	if(tick >= renewal && !busy.test_and_set())
 		start();
 }
 

=== removed file 'natpmp/natpmpc.c'
--- natpmp/natpmpc.c	2011-02-11 23:07:59 +0000
+++ natpmp/natpmpc.c	1970-01-01 00:00:00 +0000
@@ -1,225 +0,0 @@
-/* $Id: natpmpc.c,v 1.8 2011/01/03 17:31:03 nanard Exp $ */
-/* libnatpmp
- * Copyright (c) 2007-2011, Thomas BERNARD <miniupnp@xxxxxxx>
- * http://miniupnp.free.fr/libnatpmp.html
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#if defined(_MSC_VER)
-#if _MSC_VER >= 1400
-#define strcasecmp _stricmp
-#else
-#define strcasecmp stricmp
-#endif
-#else
-#include <unistd.h>
-#endif
-#ifdef WIN32
-#include <winsock2.h>
-#else
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#endif
-#include "natpmp.h"
-
-void usage(FILE * out, const char * argv0)
-{
-	fprintf(out, "Usage :\n");
-	fprintf(out, "  %s [options]\n", argv0);
-	fprintf(out, "\tdisplay the public IP address.\n");
-	fprintf(out, "  %s -h\n", argv0);
-	fprintf(out, "\tdisplay this help screen.\n");
-	fprintf(out, "  %s [options] -a <public port> <private port> <protocol> [lifetime]\n", argv0);
-	fprintf(out, "\tadd a port mapping.\n");
-	fprintf(out, "\nOption available :\n");
-	fprintf(out, "  -g ipv4address\n");
-	fprintf(out, "\tforce the gateway to be used as destination for NAT-PMP commands.\n");
-	fprintf(out, "\n  In order to remove a mapping, set it with a lifetime of 0 seconds.\n");
-	fprintf(out, "  To remove all mappings for your machine, use 0 as private port and lifetime.\n");
-}
-
-/* sample code for using libnatpmp */
-int main(int argc, char * * argv)
-{
-	natpmp_t natpmp;
-	natpmpresp_t response;
-	int r;
-	int sav_errno;
-	struct timeval timeout;
-	fd_set fds;
-	int i;
-	int protocol = 0;
-	uint16_t privateport = 0;
-	uint16_t publicport = 0;
-	uint32_t lifetime = 3600;
-	int command = 0;
-	int forcegw = 0;
-	in_addr_t gateway = 0;
-
-#ifdef WIN32
-	WSADATA wsaData;
-	int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
-	if(nResult != NO_ERROR)
-	{
-		fprintf(stderr, "WSAStartup() failed.\n");
-		return -1;
-	}
-#endif
-
-	/* argument parsing */
-	for(i=1; i<argc; i++) {
-		if(argv[i][0] == '-') {
-			switch(argv[i][1]) {
-			case 'h':
-				usage(stdout, argv[0]);
-				return 0;
-			case 'g':
-				forcegw = 1;
-				if(argc < i + 1) {
-					fprintf(stderr, "Not enough arguments for option -%c\n", argv[i][1]);
-					return 1;
-				}
-				gateway = inet_addr(argv[++i]);
-				break;
-			case 'a':
-				command = 'a';
-				if(argc < i + 3) {
-					fprintf(stderr, "Not enough arguments for option -%c\n", argv[i][1]);
-					return 1;
-				}
-				i++;
-				if(1 != sscanf(argv[i], "%hu", &publicport)) {
-					fprintf(stderr, "%s is not a correct 16bits unsigned integer\n", argv[i]);
-					return 1;
-				}
-				i++;
-				if(1 != sscanf(argv[i], "%hu", &privateport)) {
-					fprintf(stderr, "%s is not a correct 16bits unsigned integer\n", argv[i]);
-					return 1;
-				}
-				i++;
-				if(0 == strcasecmp(argv[i], "tcp"))
-					protocol = NATPMP_PROTOCOL_TCP;
-				else if(0 == strcasecmp(argv[i], "udp"))
-					protocol = NATPMP_PROTOCOL_UDP;
-				else {
-					fprintf(stderr, "%s is not a valid protocol\n", argv[i]);
-					return 1;
-				}
-				if(argc >= i) {
-					i++;
-					if(1 != sscanf(argv[i], "%u", &lifetime)) {
-						fprintf(stderr, "%s is not a correct 32bits unsigned integer\n", argv[i]);
-					}
-				}
-				break;
-			default:
-				fprintf(stderr, "Unknown option %s\n", argv[i]);
-				usage(stderr, argv[0]);
-				return 1;
-			}
-		} else {
-			fprintf(stderr, "Unknown option %s\n", argv[i]);
-			usage(stderr, argv[0]);
-			return 1;
-		}
-	}
-
-	/* initnatpmp() */
-	r = initnatpmp(&natpmp, forcegw, gateway);
-	printf("initnatpmp() returned %d (%s)\n", r, r?"FAILED":"SUCCESS");
-	if(r<0)
-		return 1;
-
-	printf("using gateway : %s\n", inet_ntoa(*((struct in_addr *)&natpmp.gateway)));
-
-	/* sendpublicaddressrequest() */
-	r = sendpublicaddressrequest(&natpmp);
-	printf("sendpublicaddressrequest returned %d (%s)\n",
-	       r, r==2?"SUCCESS":"FAILED");
-	if(r<0)
-		return 1;
-
-	do {
-		FD_ZERO(&fds);
-		FD_SET(natpmp.s, &fds);
-		getnatpmprequesttimeout(&natpmp, &timeout);
-		select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
-		r = readnatpmpresponseorretry(&natpmp, &response);
-		sav_errno = errno;
-		printf("readnatpmpresponseorretry returned %d (%s)\n",
-		       r, r==0?"OK":(r==NATPMP_TRYAGAIN?"TRY AGAIN":"FAILED"));
-		if(r<0 && r!=NATPMP_TRYAGAIN) {
-#ifdef ENABLE_STRNATPMPERR
-			fprintf(stderr, "readnatpmpresponseorretry() failed : %s\n",
-			        strnatpmperr(r));
-#endif
-			fprintf(stderr, "  errno=%d '%s'\n", 
-			        sav_errno, strerror(sav_errno));
-		}
-	} while(r==NATPMP_TRYAGAIN);
-	if(r<0)
-		return 1;
-
-	/* TODO : check that response.type == 0 */
-	printf("Public IP address : %s\n", inet_ntoa(response.pnu.publicaddress.addr));
-	printf("epoch = %u\n", response.epoch);
-
-	if(command == 'a') {
-		/* sendnewportmappingrequest() */
-		r = sendnewportmappingrequest(&natpmp, protocol,
-        	                      privateport, publicport,
-								  lifetime);
-		printf("sendnewportmappingrequest returned %d (%s)\n",
-		       r, r==12?"SUCCESS":"FAILED");
-		if(r < 0)
-			return 1;
-
-		do {
-			FD_ZERO(&fds);
-			FD_SET(natpmp.s, &fds);
-			getnatpmprequesttimeout(&natpmp, &timeout);
-			select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
-			r = readnatpmpresponseorretry(&natpmp, &response);
-			printf("readnatpmpresponseorretry returned %d (%s)\n",
-			       r, r==0?"OK":(r==NATPMP_TRYAGAIN?"TRY AGAIN":"FAILED"));
-		} while(r==NATPMP_TRYAGAIN);
-		if(r<0) {
-#ifdef ENABLE_STRNATPMPERR
-			fprintf(stderr, "readnatpmpresponseorretry() failed : %s\n",
-			        strnatpmperr(r));
-#endif
-			return 1;
-		}
-	
-		printf("Mapped public port %hu protocol %s to local port %hu "
-		       "liftime %u\n",
-	    	   response.pnu.newportmapping.mappedpublicport,
-			   response.type == NATPMP_RESPTYPE_UDPPORTMAPPING ? "UDP" :
-			    (response.type == NATPMP_RESPTYPE_TCPPORTMAPPING ? "TCP" :
-			     "UNKNOWN"),
-			   response.pnu.newportmapping.privateport,
-			   response.pnu.newportmapping.lifetime);
-		printf("epoch = %u\n", response.epoch);
-	}
-
-	r = closenatpmp(&natpmp);
-	printf("closenatpmp() returned %d (%s)\n", r, r==0?"SUCCESS":"FAILED");
-	if(r<0)
-		return 1;
-
-	return 0;
-}
-

=== modified file 'win32/Mapper_MiniUPnPc.cpp'
--- win32/Mapper_MiniUPnPc.cpp	2011-02-11 23:08:25 +0000
+++ win32/Mapper_MiniUPnPc.cpp	2011-02-12 15:11:02 +0000
@@ -33,6 +33,11 @@
 const string Mapper_MiniUPnPc::name = "MiniUPnP";
 
 bool Mapper_MiniUPnPc::init() {
+	// only init once.
+	static bool initialized = false;
+	if(initialized)
+		return true;
+
 	UPNPDev* devices = upnpDiscover(2000, 0, 0, 0);
 	if(!devices)
 		return false;
@@ -40,8 +45,8 @@
 	UPNPUrls urls;
 	IGDdatas data;
 
-	bool ret = UPNP_GetValidIGD(devices, &urls, &data, 0, 0) == 1;
-	if(ret) {
+	initialized = UPNP_GetValidIGD(devices, &urls, &data, 0, 0) == 1;
+	if(initialized) {
 		url = urls.controlURL;
 		service = data.first.servicetype;
 		device = data.CIF.friendlyName;
@@ -50,7 +55,7 @@
 	FreeUPNPUrls(&urls);
 	freeUPNPDevlist(devices);
 
-	return ret;
+	return initialized;
 }
 
 void Mapper_MiniUPnPc::uninit() {

=== modified file 'win32/Mapper_NATPMP.cpp'
--- win32/Mapper_NATPMP.cpp	2011-02-11 23:08:25 +0000
+++ win32/Mapper_NATPMP.cpp	2011-02-12 15:11:02 +0000
@@ -35,8 +35,6 @@
 static natpmp_t nat;
 
 bool Mapper_NATPMP::init() {
-	nat.s = 0;
-
 	// the lib normally handles this but we call it manually to store the result (IP of the router).
 	in_addr addr;
 	if(getdefaultgateway(reinterpret_cast<in_addr_t*>(&addr.s_addr)) < 0)
@@ -48,18 +46,6 @@
 
 void Mapper_NATPMP::uninit() {
 	closenatpmp(&nat);
-	nat.s = 0;
-}
-
-bool Mapper_NATPMP::close() {
-	if(nat.s) // during the init phase - uninit will be called by MappingManager.
-		return Mapper::close();
-	if(init()) { // out of the init phase - we must re-create a socket.
-		bool ret = Mapper::close();
-		uninit();
-		return ret;
-	}
-	return false;
 }
 
 int reqType(const Mapper::Protocol protocol) {
@@ -101,7 +87,7 @@
 	if(sendRequest(port, protocol, 3600)) {
 		natpmpresp_t response;
 		if(read(response) && response.type == respType(protocol) && response.pnu.newportmapping.mappedpublicport == port) {
-			lifetime = std::min(lifetime, response.pnu.newportmapping.lifetime);
+			lifetime = std::min(lifetime ? lifetime : 3600, response.pnu.newportmapping.lifetime);
 			return true;
 		}
 	}

=== modified file 'win32/Mapper_NATPMP.h'
--- win32/Mapper_NATPMP.h	2011-02-11 23:08:25 +0000
+++ win32/Mapper_NATPMP.h	2011-02-12 15:11:02 +0000
@@ -30,8 +30,6 @@
 	bool init();
 	void uninit();
 
-	bool close();
-
 	bool add(const unsigned short port, const Protocol protocol, const string& description);
 	bool remove(const unsigned short port, const Protocol protocol);
 

=== modified file 'win32/Mapper_WinUPnP.cpp'
--- win32/Mapper_WinUPnP.cpp	2011-02-11 23:08:25 +0000
+++ win32/Mapper_WinUPnP.cpp	2011-02-12 15:11:02 +0000
@@ -31,6 +31,11 @@
 #include <natupnp.h>
 	
 bool Mapper_WinUPnP::init() {
+	// only init once.
+	static bool initialized = false;
+	if(initialized)
+		return true;
+
 	// Lacking the __uuidof in mingw...
 	CLSID upnp;
 	OLECHAR upnps[] = L"{AE1E00AA-3FD5-403C-8A27-2BBDC30CD0E1}";
@@ -42,7 +47,8 @@
 	HRESULT hr = CoCreateInstance(upnp, 0, CLSCTX_INPROC_SERVER, iupnp, reinterpret_cast<LPVOID*>(&pUN));
 	if(FAILED(hr))
 		pUN = 0;
-	return pUN;
+	initialized = pUN;
+	return initialized;
 }
 
 void Mapper_WinUPnP::uninit() {
@@ -162,6 +168,9 @@
 	return false;
 }
 
+void Mapper_WinUPnP::uninit() {
+}
+
 bool Mapper_WinUPnP::add(const unsigned short port, const Protocol protocol, const string& description) {
 	return false;
 }