Example #1
0
void* CNetServerWorker::SetupUPnP(void*)
{
	// Values we want to set.
	char psPort[6];
	sprintf_s(psPort, ARRAY_SIZE(psPort), "%d", PS_DEFAULT_PORT);
	const char* leaseDuration = "0"; // Indefinite/permanent lease duration.
	const char* description = "0AD Multiplayer";
	const char* protocall = "UDP";
	char internalIPAddress[64];
	char externalIPAddress[40];
	// Variables to hold the values that actually get set.
	char intClient[40];
	char intPort[6];
	char duration[16];
	// Intermediate variables.
	struct UPNPUrls urls;
	struct IGDdatas data;
	struct UPNPDev* devlist = NULL;

	// Cached root descriptor URL.
	std::string rootDescURL;
	CFG_GET_VAL("network.upnprootdescurl", rootDescURL);
	if (!rootDescURL.empty())
		LOGMESSAGE("Net server: attempting to use cached root descriptor URL: %s", rootDescURL.c_str());

	int ret = 0;
	bool allocatedUrls = false;

	// Try a cached URL first
	if (!rootDescURL.empty() && UPNP_GetIGDFromUrl(rootDescURL.c_str(), &urls, &data, internalIPAddress, sizeof(internalIPAddress)))
	{
		LOGMESSAGE("Net server: using cached IGD = %s", urls.controlURL);
		ret = 1;
	}
	// No cached URL, or it did not respond. Try getting a valid UPnP device for 10 seconds.
	else if ((devlist = upnpDiscover(10000, 0, 0, 0, 0, 0)) != NULL)
	{
		ret = UPNP_GetValidIGD(devlist, &urls, &data, internalIPAddress, sizeof(internalIPAddress));
		allocatedUrls = ret != 0; // urls is allocated on non-zero return values
	}
	else
	{
		LOGMESSAGE("Net server: upnpDiscover failed and no working cached URL.");
		return NULL;
	}

	switch (ret)
	{
	case 0:
		LOGMESSAGE("Net server: No IGD found");
		break;
	case 1:
		LOGMESSAGE("Net server: found valid IGD = %s", urls.controlURL);
		break;
	case 2:
		LOGMESSAGE("Net server: found a valid, not connected IGD = %s, will try to continue anyway", urls.controlURL);
		break;
	case 3:
		LOGMESSAGE("Net server: found a UPnP device unrecognized as IGD = %s, will try to continue anyway", urls.controlURL);
		break;
	default:
		debug_warn(L"Unrecognized return value from UPNP_GetValidIGD");
	}

	// Try getting our external/internet facing IP. TODO: Display this on the game-setup page for conviniance.
	ret = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
	if (ret != UPNPCOMMAND_SUCCESS)
	{
		LOGMESSAGE("Net server: GetExternalIPAddress failed with code %d (%s)", ret, strupnperror(ret));
		return NULL;
	}
	LOGMESSAGE("Net server: ExternalIPAddress = %s", externalIPAddress);

	// Try to setup port forwarding.
	ret = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, psPort, psPort,
							internalIPAddress, description, protocall, 0, leaseDuration);
	if (ret != UPNPCOMMAND_SUCCESS)
	{
		LOGMESSAGE("Net server: AddPortMapping(%s, %s, %s) failed with code %d (%s)",
			   psPort, psPort, internalIPAddress, ret, strupnperror(ret));
		return NULL;
	}

	// Check that the port was actually forwarded.
	ret = UPNP_GetSpecificPortMappingEntry(urls.controlURL,
									 data.first.servicetype,
									 psPort, protocall,
#if defined(MINIUPNPC_API_VERSION) && MINIUPNPC_API_VERSION >= 10
									 NULL/*remoteHost*/,
#endif
									 intClient, intPort, NULL/*desc*/,
									 NULL/*enabled*/, duration);

	if (ret != UPNPCOMMAND_SUCCESS)
	{
		LOGMESSAGE("Net server: GetSpecificPortMappingEntry() failed with code %d (%s)", ret, strupnperror(ret));
		return NULL;
	}

	LOGMESSAGE("Net server: External %s:%s %s is redirected to internal %s:%s (duration=%s)",
				   externalIPAddress, psPort, protocall, intClient, intPort, duration);

	// Cache root descriptor URL to try to avoid discovery next time.
	g_ConfigDB.SetValueString(CFG_USER, "network.upnprootdescurl", urls.controlURL);
	g_ConfigDB.WriteFile(CFG_USER);
	LOGMESSAGE("Net server: cached UPnP root descriptor URL as %s", urls.controlURL);

	// Make sure everything is properly freed.
	if (allocatedUrls)
		FreeUPNPUrls(&urls);
    
	freeUPNPDevlist(devlist);

	return NULL;
}
Example #2
0
/* sample upnp client program */
int main(int argc, char ** argv)
{
	char command = 0;
	char ** commandargv = 0;
	int commandargc = 0;
	struct UPNPDev * devlist = 0;
	char lanaddr[64];	/* my ip address on the LAN */
	int i;
	const char * rootdescurl = 0;
	const char * multicastif = 0;
	const char * minissdpdpath = 0;
	int retcode = 0;
	int error = 0;
	int ipv6 = 0;
	const char * description = 0;

#ifdef _WIN32
	WSADATA wsaData;
	int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
	if(nResult != NO_ERROR)
	{
		fprintf(stderr, "WSAStartup() failed.\n");
		return -1;
	}
#endif
    printf("upnpc : miniupnpc library test client. (c) 2005-2014 Thomas Bernard\n");
    printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n"
	       "for more information.\n");
	/* command line processing */
	for(i=1; i<argc; i++)
	{
		if(0 == strcmp(argv[i], "--help") || 0 == strcmp(argv[i], "-h"))
		{
			command = 0;
			break;
		}
		if(argv[i][0] == '-')
		{
			if(argv[i][1] == 'u')
				rootdescurl = argv[++i];
			else if(argv[i][1] == 'm')
				multicastif = argv[++i];
			else if(argv[i][1] == 'p')
				minissdpdpath = argv[++i];
			else if(argv[i][1] == '6')
				ipv6 = 1;
			else if(argv[i][1] == 'e')
				description = argv[++i];
			else
			{
				command = argv[i][1];
				i++;
				commandargv = argv + i;
				commandargc = argc - i;
				break;
			}
		}
		else
		{
			fprintf(stderr, "option '%s' invalid\n", argv[i]);
		}
	}

	if(!command 
	   || (command == 'a' && commandargc<4)
	   || (command == 'd' && argc<2)
	   || (command == 'r' && argc<2)
	   || (command == 'A' && commandargc<6)
	   || (command == 'U' && commandargc<2)
	   || (command == 'D' && commandargc<1))
	{
		fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol [duration]\n\t\tAdd port redirection\n", argv[0]);
		fprintf(stderr, "       \t%s [options] -d external_port protocol <remote host>\n\t\tDelete port redirection\n", argv[0]);
		fprintf(stderr, "       \t%s [options] -s\n\t\tGet Connection status\n", argv[0]);
		fprintf(stderr, "       \t%s [options] -l\n\t\tList redirections\n", argv[0]);
		fprintf(stderr, "       \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings (for IGD:2 only)\n", argv[0]);
		fprintf(stderr, "       \t%s [options] -n ip port external_port protocol [duration]\n\t\tAdd (any) port redirection allowing IGD to use alternative external_port (for IGD:2 only)\n", argv[0]);
		fprintf(stderr, "       \t%s [options] -N external_port_start external_port_end protocol [manage]\n\t\tDelete range of port redirections (for IGD:2 only)\n", argv[0]);
		fprintf(stderr, "       \t%s [options] -r port1 [external_port1] protocol1 [port2 [external_port2] protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]);
		fprintf(stderr, "       \t%s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time\n\t\tAdd Pinhole (for IGD:2 only)\n", argv[0]);
		fprintf(stderr, "       \t%s [options] -U uniqueID new_lease_time\n\t\tUpdate Pinhole (for IGD:2 only)\n", argv[0]);
		fprintf(stderr, "       \t%s [options] -C uniqueID\n\t\tCheck if Pinhole is Working (for IGD:2 only)\n", argv[0]);
		fprintf(stderr, "       \t%s [options] -K uniqueID\n\t\tGet Number of packets going through the rule (for IGD:2 only)\n", argv[0]);
		fprintf(stderr, "       \t%s [options] -D uniqueID\n\t\tDelete Pinhole (for IGD:2 only)\n", argv[0]);
		fprintf(stderr, "       \t%s [options] -S\n\t\tGet Firewall status (for IGD:2 only)\n", argv[0]);
		fprintf(stderr, "       \t%s [options] -G remote_ip remote_port internal_ip internal_port protocol\n\t\tGet Outbound Pinhole Timeout (for IGD:2 only)\n", argv[0]);
		fprintf(stderr, "       \t%s [options] -P\n\t\tGet Presentation url\n", argv[0]);
		fprintf(stderr, "\nprotocol is UDP or TCP\n");
		fprintf(stderr, "Options:\n");
		fprintf(stderr, "  -e description : set description for port mapping.\n");
		fprintf(stderr, "  -6 : use ip v6 instead of ip v4.\n");
		fprintf(stderr, "  -u url : bypass discovery process by providing the XML root description url.\n");
		fprintf(stderr, "  -m address/interface : provide ip address (ip v4) or interface name (ip v4 or v6) to use for sending SSDP multicast packets.\n");
		fprintf(stderr, "  -p path : use this path for MiniSSDPd socket.\n");
		return 1;
	}

	if( rootdescurl
	  || (devlist = upnpDiscover(2000, multicastif, minissdpdpath,
	                             0/*sameport*/, ipv6, &error)))
	{
		struct UPNPDev * device;
		struct UPNPUrls urls;
		struct IGDdatas data;
		if(devlist)
		{
			printf("List of UPNP devices found on the network :\n");
			for(device = devlist; device; device = device->pNext)
			{
				printf(" desc: %s\n st: %s\n\n",
					   device->descURL, device->st);
			}
		}
		else if(!rootdescurl)
		{
			printf("upnpDiscover() error code=%d\n", error);
		}
		i = 1;
		if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr)))
		  || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))))
		{
			switch(i) {
			case 1:
				printf("Found valid IGD : %s\n", urls.controlURL);
				break;
			case 2:
				printf("Found a (not connected?) IGD : %s\n", urls.controlURL);
				printf("Trying to continue anyway\n");
				break;
			case 3:
				printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL);
				printf("Trying to continue anyway\n");
				break;
			default:
				printf("Found device (igd ?) : %s\n", urls.controlURL);
				printf("Trying to continue anyway\n");
			}
			printf("Local LAN ip address : %s\n", lanaddr);
			#if 0
			printf("getting \"%s\"\n", urls.ipcondescURL);
			descXML = miniwget(urls.ipcondescURL, &descXMLsize);
			if(descXML)
			{
				/*fwrite(descXML, 1, descXMLsize, stdout);*/
				free(descXML); descXML = NULL;
			}
			#endif

			switch(command)
			{
			case 'l':
				DisplayInfos(&urls, &data);
				ListRedirections(&urls, &data);
				break;
			case 'L':
				NewListRedirections(&urls, &data);
				break;
			case 'a':
				SetRedirectAndTest(&urls, &data,
						   commandargv[0], commandargv[1],
						   commandargv[2], commandargv[3],
						   (commandargc > 4)?commandargv[4]:"0",
						   description, 0);
				break;
			case 'd':
				RemoveRedirect(&urls, &data, commandargv[0], commandargv[1],
				               commandargc > 2 ? commandargv[2] : NULL);
				break;
			case 'n':	/* aNy */
				SetRedirectAndTest(&urls, &data,
						   commandargv[0], commandargv[1],
						   commandargv[2], commandargv[3],
						   (commandargc > 4)?commandargv[4]:"0",
						   description, 1);
				break;
			case 'N':
				if (commandargc < 3)
					fprintf(stderr, "too few arguments\n");

				RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2],
						    commandargc > 3 ? commandargv[3] : NULL);
				break;
			case 's':
				GetConnectionStatus(&urls, &data);
				break;
			case 'r':
				i=0;
				while(i<commandargc){
					if(!is_int(commandargv[i+1])){
						/* 2nd parameter not an integer, so format is '<port> <protocol>' */
						/* Note: no 2nd parameter is also not-an-integer, and will lead to a "Wrong arguments" */
						SetRedirectAndTest(&urls, &data,
								   lanaddr, commandargv[i],
								   commandargv[i], commandargv[i+1], "0",
								   description, 0);
						i+=2;	/* 2 parameters parsed */
					} else {
						/* 2nd parameter is an integer, so format is '<port> <external_port> <protocol>' */
						SetRedirectAndTest(&urls, &data,
								   lanaddr, commandargv[i],
								   commandargv[i+1], commandargv[i+2], "0",
								   description, 0);
						i+=3;	/* 3 parameters parsed */
					}
				}
				break;
			case 'A':
				SetPinholeAndTest(&urls, &data,
				                  commandargv[0], commandargv[1],
				                  commandargv[2], commandargv[3],
				                  commandargv[4], commandargv[5]);
				break;
			case 'U':
				GetPinholeAndUpdate(&urls, &data,
				                   commandargv[0], commandargv[1]);
				break;
			case 'C':
				for(i=0; i<commandargc; i++)
				{
					CheckPinhole(&urls, &data, commandargv[i]);
				}
				break;
			case 'K':
				for(i=0; i<commandargc; i++)
				{
					GetPinholePackets(&urls, &data, commandargv[i]);
				}
				break;
			case 'D':
				for(i=0; i<commandargc; i++)
				{
					RemovePinhole(&urls, &data, commandargv[i]);
				}
				break;
			case 'S':
				GetFirewallStatus(&urls, &data);
				break;
			case 'G':
				GetPinholeOutboundTimeout(&urls, &data,
							commandargv[0], commandargv[1],
							commandargv[2], commandargv[3],
							commandargv[4]);
				break;
			case 'P':
				printf("Presentation URL found:\n");
				printf("            %s\n", data.presentationurl);
				break;
			default:
				fprintf(stderr, "Unknown switch -%c\n", command);
				retcode = 1;
			}

			FreeUPNPUrls(&urls);
		}
		else
		{
			fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n");
			retcode = 1;
		}
		freeUPNPDevlist(devlist); devlist = 0;
	}
	else
	{
		fprintf(stderr, "No IGD UPnP Device found on the network !\n");
		retcode = 1;
	}
#ifdef _WIN32
	nResult = WSACleanup();
	if(nResult != NO_ERROR) {
		fprintf(stderr, "WSACleanup() failed.\n");
	}
#endif /* _WIN32 */
	return retcode;
}
Example #3
0
/* sample upnp client program */
int main(int argc, char ** argv)
{
    char command = 0;
    char ** commandargv = 0;
    int commandargc = 0;
    struct UPNPDev * devlist = 0;
    char lanaddr[64];	/* my ip address on the LAN */
    int i;
    const char * rootdescurl = 0;
    const char * multicastif = 0;
    const char * minissdpdpath = 0;
    int retcode = 0;

#ifdef WIN32
    WSADATA wsaData;
    int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if(nResult != NO_ERROR)
    {
        fprintf(stderr, "WSAStartup() failed.\n");
        return -1;
    }
#endif
    printf("upnpc : miniupnpc library test client. (c) 2006-2010 Thomas Bernard\n");
    printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n"
           "for more information.\n");
    /* command line processing */
    for(i=1; i<argc; i++)
    {
        if(argv[i][0] == '-')
        {
            if(argv[i][1] == 'u')
                rootdescurl = argv[++i];
            else if(argv[i][1] == 'm')
                multicastif = argv[++i];
            else if(argv[i][1] == 'p')
                minissdpdpath = argv[++i];
            else
            {
                command = argv[i][1];
                i++;
                commandargv = argv + i;
                commandargc = argc - i;
                break;
            }
        }
        else
        {
            fprintf(stderr, "option '%s' invalid\n", argv[i]);
        }
    }

    if(!command || (command == 'a' && commandargc<4)
            || (command == 'd' && argc<2)
            || (command == 'r' && argc<2))
    {
        fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol\n\t\tAdd port redirection\n", argv[0]);
        fprintf(stderr, "       \t%s [options] -d external_port protocol [port2 protocol2] [...]\n\t\tDelete port redirection\n", argv[0]);
        fprintf(stderr, "       \t%s [options] -s\n\t\tGet Connection status\n", argv[0]);
        fprintf(stderr, "       \t%s [options] -l\n\t\tList redirections\n", argv[0]);
        fprintf(stderr, "       \t%s [options] -r port1 protocol1 [port2 protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]);
        fprintf(stderr, "\nprotocol is UDP or TCP\n");
        fprintf(stderr, "Options:\n");
        fprintf(stderr, "  -u url : bypass discovery process by providing the XML root description url.\n");
        fprintf(stderr, "  -m address : provide ip address of the interface to use for sending SSDP multicast packets.\n");
        fprintf(stderr, "  -p path : use this path for MiniSSDPd socket.\n");
        return 1;
    }

    if( rootdescurl
            || (devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0)))
    {
        struct UPNPDev * device;
        struct UPNPUrls urls;
        struct IGDdatas data;
        if(devlist)
        {
            printf("List of UPNP devices found on the network :\n");
            for(device = devlist; device; device = device->pNext)
            {
                printf(" desc: %s\n st: %s\n\n",
                       device->descURL, device->st);
            }
        }
        i = 1;
        if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr)))
                || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))))
        {
            switch(i) {
            case 1:
                printf("Found valid IGD : %s\n", urls.controlURL);
                break;
            case 2:
                printf("Found a (not connected?) IGD : %s\n", urls.controlURL);
                printf("Trying to continue anyway\n");
                break;
            case 3:
                printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL);
                printf("Trying to continue anyway\n");
                break;
            default:
                printf("Found device (igd ?) : %s\n", urls.controlURL);
                printf("Trying to continue anyway\n");
            }
            printf("Local LAN ip address : %s\n", lanaddr);
#if 0
            printf("getting \"%s\"\n", urls.ipcondescURL);
            descXML = miniwget(urls.ipcondescURL, &descXMLsize);
            if(descXML)
            {
                /*fwrite(descXML, 1, descXMLsize, stdout);*/
                free(descXML);
                descXML = NULL;
            }
#endif

            switch(command)
            {
            case 'l':
                DisplayInfos(&urls, &data);
                ListRedirections(&urls, &data);
                break;
            case 'a':
                SetRedirectAndTest(&urls, &data,
                                   commandargv[0], commandargv[1],
                                   commandargv[2], commandargv[3]);
                break;
            case 'd':
                for(i=0; i<commandargc; i+=2)
                {
                    RemoveRedirect(&urls, &data, commandargv[i], commandargv[i+1]);
                }
                break;
            case 's':
                GetConnectionStatus(&urls, &data);
                break;
            case 'r':
                for(i=0; i<commandargc; i+=2)
                {
                    /*printf("port %s protocol %s\n", argv[i], argv[i+1]);*/
                    SetRedirectAndTest(&urls, &data,
                                       lanaddr, commandargv[i],
                                       commandargv[i], commandargv[i+1]);
                }
                break;
            default:
                fprintf(stderr, "Unknown switch -%c\n", command);
                retcode = 1;
            }

            FreeUPNPUrls(&urls);
        }
        else
        {
            fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n");
            retcode = 1;
        }
        freeUPNPDevlist(devlist);
        devlist = 0;
    }
    else
    {
        fprintf(stderr, "No IGD UPnP Device found on the network !\n");
        retcode = 1;
    }
    return retcode;
}