⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 upnp.cpp

📁 非常难得的eMule(电骡) V0.45b 源码下载 值得研究
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	if(!isComplete())return false;
	CString post, host, addr;
	int port = 0;
	addr = NGetAddressFromUrl(m_controlurl, post, host, port);
	if(addr.IsEmpty())return false;
	CString cnt;
	CString psr;
	cnt.Append(_T("<?xml version=\"1.0\"?><s:Envelope\r\n    xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"\r\n    "));
	cnt.Append(_T("s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n  <s:Body>\r\n    <u:"));
	cnt.Append(name);
	cnt.Append(_T(" xmlns:u=\""));
	cnt.Append(m_name);
	cnt.Append(_T("\">\r\n"));
	cnt.Append(args);
	cnt.Append(_T("    </u:"));
	cnt.Append(name);
	cnt.Append(_T(">\r\n  </s:Body>\r\n</s:Envelope>\r\n\r\n"));
	psr.Append(_T("POST "));
	psr.Append(post);
	psr.Append(_T(" HTTP/1.1\r\nHOST: "));
	psr.Append(host);
	psr.Append(_T("\r\nContent-Length: "));
	psr.Append(getString(CStringA(cnt).GetLength()));
	psr.Append(_T("\r\nContent-Type: text/xml; charset=\"utf-8\"\r\nSOAPAction: \""));
	psr.Append(m_name);
	psr.Append(_T("#"));
	psr.Append(name);
	psr.Append(_T("\"\r\n\r\n"));
	psr.Append(cnt);

	CString response;
	CString request = psr;
	if (!SOAP_action(addr, port, request, response)) return false;
	CString result;
	if (!parseHTTPResponse(response, result)) return false;

	return true;
}

bool MyUPnP::addPortmap(int eport, int iport, const CString& iclient, const CString& descri, const CString& type)
{
	CString args;

	args.Empty();
	args.Append(GetArgString(_T("NewRemoteHost"), _T("")));
	args.Append(GetArgString(_T("NewExternalPort"), eport));
	args.Append(GetArgString(_T("NewProtocol"), type));
	args.Append(GetArgString(_T("NewInternalPort"), iport));
	args.Append(GetArgString(_T("NewInternalClient"), iclient));
	args.Append(GetArgString(_T("NewEnabled"), _T("1")));
	args.Append(GetArgString(_T("NewPortMappingDescription"), descri));
	args.Append(GetArgString(_T("NewLeaseDuration"), 0));

	return InvokeCommand(UPNPADDPORTMAP, args);
}

bool MyUPnP::deletePortmap(int eport, const CString& type)
{
	CString args;

	args.Empty();
	args.Append(GetArgString(_T("NewRemoteHost"), _T("")));
	args.Append(GetArgString(_T("NewExternalPort"), eport));
	args.Append(GetArgString(_T("NewProtocol"), type));

	return InvokeCommand(UPNPDELPORTMAP, args);
}

/////////////////////////////////////////////////////////////////////////////////
// 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(_T("You aren't behind a Hardware Firewall or Router"));
		return UNAT_NOT_IN_LAN;
	}
	
	if (!isComplete()) {
		Search();
		if (!isComplete()) {
			SetLastError(_T("Can not found a UPnP Router"));
			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;

	int retries = 255;
	WORD rndPort = mapping->externalPort;
	for (int retries = 255; retries; 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);
			return UNAT_OK;
		}

		if (!tryRandom) {
			SetLastError(_T("External NAT port in use"));
			return UNAT_EXTERNAL_PORT_IN_USE;
		}

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

	SetLastError(_T("External NAT port in use: Too many retries"));
	return UNAT_EXTERNAL_PORT_IN_USE;
}

/////////////////////////////////////////////////////////////////////////////////
// Removes a NAT Port Mapping
// Params:
//		UPNPNAT_MAPPING *mapping  ->  Port Mapping Data
//			Should be the same struct passed to AddNATPortMapping
//		bool removeFromList	-> Remove the port mapping from the internal list
//			Should by allways true (dafault value if not passed).
//			If you set it to false can cause an unexpected error.
//
//
// Return:
//		UNAT_OK:
//			Successfull.
//		UNAT_NOT_OWNED_PORTMAPPING:
//			Error, you are trying to remove a port mapping not owned by this class
//		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::RemoveNATPortMapping(UPNPNAT_MAPPING mapping, bool removeFromList)
{
	if(!IsLANIP(GetLocalIP())){
		SetLastError(_T("You aren't behind a Hardware Firewall or Router"));
		return UNAT_NOT_IN_LAN;
	}

	if (!isComplete()) {
		Search();
		if (!isComplete()) {
			SetLastError(_T("Can not found a UPnP Router"));
			return UNAT_ERROR;
		}
	}

	for(POSITION pos = m_Mappings.GetHeadPosition(); pos!=NULL; m_Mappings.GetNext(pos)){
		UPNPNAT_MAPPING search = m_Mappings.GetAt(pos);

		if (search.externalPort == mapping.externalPort 
			&& search.protocol == mapping.protocol)
		{
			CString Proto;

			if (mapping.protocol == UNAT_TCP)
				Proto = _T("TCP");
			else
				Proto = _T("UDP");

			if (deletePortmap(mapping.externalPort, Proto)) {
				if(removeFromList)
					m_Mappings.RemoveAt(pos);
				return UNAT_OK;
			} else {
				SetLastError(_T("Error getting StaticPortMappingCollection"));
				return UNAT_ERROR;
			}
		}
	}

	SetLastError(_T("Port mapping not owned by this class"));
	return UNAT_NOT_OWNED_PORTMAPPING;
}

void MyUPnP::clearNATPortMapping()
{
	UPNPNAT_MAPPING search;
	POSITION pos = m_Mappings.GetHeadPosition();
	while(pos){
		search = m_Mappings.GetNext(pos);
		RemoveNATPortMapping(search, false);
	}

	m_Mappings.RemoveAll();
}

/////////////////////////////////////////////////////////////////////////////////
// Initializes m_localIP variable, for future access to GetLocalIP()
/////////////////////////////////////////////////////////////////////////////////
void MyUPnP::InitLocalIP()
{
#ifndef _DEBUG
	try
#endif
	{
		char szHost[256];
		if (gethostname(szHost, sizeof szHost) == 0){
			hostent* pHostEnt = gethostbyname(szHost);
			if (pHostEnt != NULL && pHostEnt->h_length == 4 && pHostEnt->h_addr_list[0] != NULL){
				UPNPNAT_MAPPING mapping;
				struct in_addr addr;

				memcpy(&addr, pHostEnt->h_addr_list[0], sizeof(struct in_addr));
				m_slocalIP = inet_ntoa(addr);
				m_uLocalIP = addr.S_un.S_addr;
			}
			else{
				m_slocalIP = _T("");
				m_uLocalIP = 0;
			}
		}
		else{
			m_slocalIP = _T("");
			m_uLocalIP = 0;
		}
	}
#ifndef _DEBUG
	catch(...){
		m_slocalIP = _T("");
		m_uLocalIP = 0;
	}
#endif
}

/////////////////////////////////////////////////////////////////////////////////
// Returns the Local IP
/////////////////////////////////////////////////////////////////////////////////
WORD MyUPnP::GetLocalIP()
{
	if(m_uLocalIP == 0)
		InitLocalIP();
	
	return m_uLocalIP;
}

/////////////////////////////////////////////////////////////////////////////////
// Returns a CString with the local IP in format xxx.xxx.xxx.xxx
/////////////////////////////////////////////////////////////////////////////////
CString MyUPnP::GetLocalIPStr()
{
	if(m_slocalIP.IsEmpty())
		InitLocalIP();
	
	return m_slocalIP;
}

/////////////////////////////////////////////////////////////////////////////////
// Sets the value of m_lastError (last error description)
/////////////////////////////////////////////////////////////////////////////////
void MyUPnP::SetLastError(CString error)	{
	m_slastError = error;
};

/////////////////////////////////////////////////////////////////////////////////
// Returns the last error description in a CString
/////////////////////////////////////////////////////////////////////////////////
CString MyUPnP::GetLastError()
{ 
	return m_slastError; 
}

/////////////////////////////////////////////////////////////////////////////////
// Returns true if nIP is a LAN ip, false otherwise
/////////////////////////////////////////////////////////////////////////////////
bool MyUPnP::IsLANIP(WORD nIP){
// filter LAN IP's
// -------------------------------------------
// 0.*
// 10.0.0.0 - 10.255.255.255  class A
// 172.16.0.0 - 172.31.255.255  class B
// 192.168.0.0 - 192.168.255.255 class C

	unsigned char nFirst = (unsigned char)nIP;
	unsigned char nSecond = (unsigned char)(nIP >> 8);

	if (nFirst==192 && nSecond==168) // check this 1st, because those LANs IPs are mostly spreaded
		return true;

	if (nFirst==172 && nSecond>=16 && nSecond<=31)
		return true;

	if (nFirst==0 || nFirst==10)
		return true;

	return false; 
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -