Пример #1
0
/////////////////////////////////////////////////////////////////////////////////
// Adds a NAT Port Mapping
// Params:
//		UPNPNAT_MAPPING *mapping  ->  Port Mapping Data
//			If mapping->externalPort is 0, then
//			mapping->externalPort gets the value of mapping->internalPort
//		bool tryRandom:
//			If If mapping->externalPort is in use, tries to find a free
//			random external port.
//
// Return:
//		UNAT_OK:
//			Successfull.
//		UNAT_EXTERNAL_PORT_IN_USE:
//			Error, you are trying to add a port mapping with an external port
//			in use.
//		UNAT_NOT_IN_LAN:
//			Error, you aren't in a LAN -> no router or firewall
//		UNAT_ERROR:
//			Error, use GetLastError() to get an error description.
/////////////////////////////////////////////////////////////////////////////////
MyUPnP::UPNPNAT_RETURN MyUPnP::AddNATPortMapping(UPNPNAT_MAPPING *mapping, bool tryRandom)
{
	CString	ProtoStr, Proto;

	if(!IsLANIP(GetLocalIP())){
		SetLastError(GetResString(IDS_UPNPSTATUS_NOTINLAN)); //zz_fly :: localize output
		return UNAT_NOT_IN_LAN;
	}
	
	if (!isComplete()) {
		Search();
		if (!isComplete()) {
			SetLastError(GetResString(IDS_UPNPSTATUS_ERROR)); //zz_fly :: localize output
			return UNAT_ERROR;
		}
	}

	if (mapping->protocol == UNAT_TCP){
		Proto = _T("TCP");
		ProtoStr = _T("TCP");
	}
	else {
		Proto = _T("UDP");
		ProtoStr = _T("UDP");
	}

	if(mapping->externalPort == 0)
		mapping->externalPort = mapping->internalPort;

	//WORD rndPort = mapping->externalPort;
	for (int retries = 200; retries>0; retries--) {
		CString Desc;
		Desc.Format(_T("eMule (%s) [%s: %u]"), mapping->description, ProtoStr, mapping->externalPort);

		if (addPortmap(mapping->externalPort, mapping->internalPort, GetLocalIPStr(), Desc, Proto)) {
			m_Mappings.AddTail(*mapping);
			SetLastError(GetResString(IDS_UPNPSTATUS_OK)); //zz_fly :: localize output
			return UNAT_OK;
		}

		if (!tryRandom) {
			SetLastError(GetResString(IDS_UPNPSTATUS_PORTINUSE)); //zz_fly :: localize output
			return UNAT_EXTERNAL_PORT_IN_USE;
		}

		mapping->externalPort = (WORD)(2049 + (65535 - 2049) * rand() / (RAND_MAX + 1));
	}

	SetLastError(GetResString(IDS_UPNPSTATUS_PORTINUSE2)); //zz_fly :: localize output
	return UNAT_EXTERNAL_PORT_IN_USE;
}
Пример #2
0
HRESULT CUPnpMgr::AddNATPortMapping(CUPnpNatMapping &mapping, BOOL bTryRandom)
{
	CSingleLock		localLock(&m_cs, TRUE);
	
	if(!IsLANIP(GetLocalIP()))
		return E_UNAT_NOT_IN_LAN;

	if (FAILED(m_nat.SearchDevice()))
		return E_UNAT_CANNOT_FIND_ROUTER;

	
	HRESULT		hr;
	CString		strDesc;
	int			i;

	if(0 == mapping.m_wExternalPort)
		mapping.m_wExternalPort = mapping.m_wInternalPort;

	mapping.m_strInternalClient = GetLocalIPStr();

	for (i = 0; i < RANDOM_RETRY_TIMES; i++)
	{
		strDesc.Format(_T("%s [%s: %u]"), mapping.m_strDescription, mapping.m_strProtocol, mapping.m_wExternalPort);

		hr = m_nat.AddPortMapping(CString(_T("")),
									mapping.m_wExternalPort, mapping.m_strProtocol,
									mapping.m_wInternalPort, mapping.m_strInternalClient,
									strDesc);


		switch(hr)
		{
		case S_OK:
			{
				CString		strInternalClient;
				hr = m_nat.GetSpecificPortMappingEntry(CString(_T("")),
														mapping.m_wExternalPort, mapping.m_strProtocol,
														NULL, &strInternalClient, NULL, NULL, NULL);
				if (SUCCEEDED(hr)
					&& strInternalClient == mapping.m_strInternalClient)			//	看PortMapping是否真的加进去了。
				{
					CUPnpNatMappingKey key;
					key.m_strRemoteHost.Empty();
					key.m_usExternalPort = mapping.m_wExternalPort;
					key.m_strProtocol = mapping.m_strProtocol;
					m_setAddedMapping.insert(key);

					WriteAddedMappingToFile();

					return S_OK;
				}
				else											//	如果添加请求成功返回而又不在列表中,则有可能是列表已满。
					return E_UNAT_ENTRY_MAYBE_FULL;

				break;
			}
		case E_UNAT_ACTION_HTTP_ERRORCODE:
			{
				if (718 == m_nat.GetLastActionErrorCode() && bTryRandom)
					mapping.m_wExternalPort = (WORD)(2049 + (65535 - 2049) * 1 *rand() / (RAND_MAX + 1));
				else
					return E_UNAT_ACTION_HTTP_ERRORCODE;
				break;
			}
		case E_UNAT_TIMEOUT:
			{
				//	为防止可能出现“实际加上了”但等待回复超时的情况,凡是执行了操作的都记下来,以便之后尝试清除一下。
				
				CUPnpNatMappingKey key;
				key.m_strRemoteHost.Empty();
				key.m_usExternalPort = mapping.m_wExternalPort;
				key.m_strProtocol = mapping.m_strProtocol;
				m_setAddedMapping.insert(key);

				WriteAddedMappingToFile();

				return E_UNAT_TIMEOUT;		//	超时未返回则直接返回,而不去重试。(因为此刻可能实际上添加成功,而不停去添加,可能造成路由器表项充满。)
				break;
			}
		default:
			return hr;
		}
	}

	return E_UNAT_REACH_RAND_PORT_RETRY_TIMES;
}
Пример #3
0
BOOL CUPnpMgr::CleanedFillupBug()
{
	CSingleLock		localLock(&m_cs, TRUE);
	
	if (FAILED(m_nat.SearchDevice()))
		return FALSE;


	HRESULT		hr;
	USHORT		usIndex;
	USHORT		usExternalPort;
	CString		strProtocol;
	CString		strDesc;
	CString		strInternalClient;
	CString		strLocalIP;
	
	CArray<CUPnpNatMapping, const CUPnpNatMapping&>		arrMapping;
	CUPnpNatMapping										mapping;

	strLocalIP = GetLocalIPStr();

	for (usIndex = 0; usIndex < 128; usIndex++)		//	最多查询128项,以防止有些路由器可能会一直返回成功。
	{
		hr = m_nat.GetGenericPortMappingEntry(usIndex, NULL, &usExternalPort, &strProtocol,
												NULL, &strInternalClient, NULL, &strDesc);

		if (-1 != strDesc.Find(_T("eMule (")))			//	描述里包含指定字样
		{
			if (strInternalClient == strLocalIP)	//	是本机添加的映射
				m_nat.DeletePortMapping(CString(_T("")),usExternalPort, strProtocol);
			else
			{
				mapping.m_strInternalClient = strInternalClient;
				mapping.m_wExternalPort = usExternalPort;
				mapping.m_strProtocol = strProtocol;	
				arrMapping.Add(mapping);
			}
		}

		if (FAILED(hr))		//	返回Failed结果,表示已经全部取完了。
			break;
	}

	
	//	如果同一ip做的eMule映射超过3项,则很有可能是以前的bug所致。则清除。<begin>
	int			i;
	int			iMappingCount;
	CString		strTestIp;

	while (! arrMapping.IsEmpty())
	{
		strTestIp = arrMapping[0].m_strInternalClient;
		iMappingCount = 0;
		for (i = 0; i < arrMapping.GetCount(); i++)
		{
			if (strTestIp == arrMapping[i].m_strInternalClient)
				iMappingCount++;
		}

		for (i = arrMapping.GetCount() - 1; i >= 0; i--)
		{
			if (strTestIp == arrMapping[i].m_strInternalClient)
			{
				if (iMappingCount > 3)			
				{
					m_nat.DeletePortMapping(CString(_T("")),
											arrMapping[i].m_wExternalPort,
											arrMapping[i].m_strProtocol);
				}

				arrMapping.RemoveAt(i);
			}

		}
	}
	//	如果同一ip做的eMule映射超过3项,则很有可能是以前的bug所致。则清除。<end>


	return TRUE;


}